Rendering SVG elements in rsx! generated via a JS function/wasm-bindgen #453
-
I am attempting this Yew + D3.js example while I learn Dioxus: https://github.com/ivanschuetz/yew-d3-example/blob/main/src/main.rs In short, I bind a D3.js function that outputs SVG with wasm-bindgen, and then mock up a Chart component using a future hook. Here is some scrappy/psuedo Chart component code, forgive me if some is incorrect. The use dioxus::prelude::*;
use wasm_bindgen::JsValue;
use super::chart_provider::{Provider, Tick};
use super::bindings;
fn show_chart(ticks: Vec<Tick>) {
bindings::show_chart(JsValue::from_serde(&ticks).unwrap());
}
#[derive(Props, PartialEq)]
pub struct ChartProps {
ticks: String
}
// Chart is a Dioxus component builder for rendering the results of a D3.js SVG chart.
pub fn Chart(cx: Scope<ChartProps>) -> Element {
let provider = Provider {};
let data = use_future(&cx, (), |_| async move {
provider
.fetch_chart()
.await
.unwrap()
});
cx.render(match data.value() {
Some(ticks) => rsx!(
div {
show_chart(ticks), // <- best practice on generating a VNode from the SVG element output?
}
),
Some(_) => rsx!("Chart failed to load."),
None => rsx!("Nothing yet..."),
})
} The idea for this basic example is to async load a D3 chart with inputs from a mock data source. Looking through the docs, I see that some wrapper having Is that the correct approach? Is there a better, more "idiomatic" Dioxus way? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
If you're getting plain SVG back from the provider, then you can use I do the same for some plotly charts I've made before: We also use this approach in loading pre-rendered markdown into the docsite: https://github.com/DioxusLabs/docsite/blob/master/src/components/blog/mod.rs#L89 If you're not getting plain SVG and need to call the script:We have a An alternative, if your script is expecting an element by ID, is to always render the d3 container with a custom ID, and execute the show_chart after the data is ready: #[inline_props]
pub fn Chart(cx: Scope, ticks: String) -> Element {
use_future(&cx, (ticks), |(ticks)| async move {
let provider = Provider {};
let data = provider
.fetch_chart()
.await
.unwrap();
bindings::show_chart(JsValue::from_serde(&data).unwrap());
});
cx.render(rsx!( svg { id: "d3-plot" } ))
} |
Beta Was this translation helpful? Give feedback.
If you're getting plain SVG back from the provider, then you can use
dangerous_inner_html
directly. It should also be faster.https://dioxuslabs.com/guide/elements/special_attributes.html#the-html-escape-hatch-dangerous_inner_html
I do the same for some plotly charts I've made before:
https://github.com/jkelleyrtp/marketplace/blob/30d72660a6e1c4f33035223e377725b61bc54b2a/src/components/results.rs#L290-L327
We also use this approach in loading pre-rendered markdown into the docsite:
https://github.com/DioxusLabs/docsite/blob/master/src/components/blog/mod.rs#L89
If you're not getting plain SVG and need to call the script:
We have a
use_eval
hook that lets you call JS directly.An alternati…