yew_plotly/
lib.rs

1//! [Yew](https://yew.rs) wrapper for [plotly.js](https://plot.ly/javascript/)
2//!
3//! Provides a yew component wrapper around the plot.ly charting library.
4
5use plotly::Plot;
6use yew::prelude::*;
7
8/// Re-exported plotly crate
9pub use plotly;
10
11/// Properties for the [Plotly] component
12#[derive(Properties, Clone, PartialEq)]
13pub struct PlotlyProps {
14    /// Plot data and layout
15    pub plot: Plot,
16}
17
18/// Plotly component wrapper
19///
20/// # Examples
21///
22/// ```
23/// # use yew::prelude::*;
24/// # use yew_plotly::plotly::{Plot, Scatter};
25/// # use yew_plotly::Plotly;
26/// # use yew_plotly::plotly::common::Mode;
27/// #
28/// #[function_component(MyPlot)]
29/// fn my_plot() -> Html {
30///     let mut plot = Plot::new();
31///     let x_values = vec![1, 2, 3];
32///     let y_values = vec![1, 3, 2];
33///
34///     let trace = Scatter::new(x_values, y_values)
35///         .mode(Mode::LinesMarkersText)
36///         .name("Scatter");
37///
38///     plot.add_trace(trace);
39///
40///     html! { <Plotly plot={plot}/> }
41/// }
42/// ```
43pub struct Plotly {
44    /// Reference to the parent DOM node
45    node_ref: NodeRef,
46}
47
48impl Component for Plotly {
49    type Message = ();
50    type Properties = PlotlyProps;
51
52    fn create(_ctx: &Context<Self>) -> Self {
53        Plotly {
54            node_ref: NodeRef::default(),
55        }
56    }
57
58    fn view(&self, _ctx: &Context<Self>) -> Html {
59        html! {
60            <div ref={ self.node_ref.clone() } />
61        }
62    }
63
64    fn destroy(&mut self, _ctx: &Context<Self>) {
65        if let Some(node) = self.node_ref.get() {
66            PlotlyJS::purge(node.into());
67        }
68    }
69
70    fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
71        if let Some(node) = self.node_ref.get() {
72            let props_obj = ctx.props().plot.to_js_object().into();
73            if first_render {
74                PlotlyJS::newPlot(node.into(), props_obj);
75            } else {
76                PlotlyJS::react(node.into(), props_obj.into());
77            }
78        }
79    }
80}
81
82#[allow(non_snake_case)]
83mod PlotlyJS {
84    use wasm_bindgen::prelude::*;
85
86    #[wasm_bindgen(js_namespace = Plotly)]
87    extern "C" {
88        pub(crate) fn newPlot(node: JsValue, obj: JsValue);
89        pub(crate) fn react(node: JsValue, obj: JsValue);
90        pub(crate) fn purge(node: JsValue);
91    }
92}