Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Custom component: Passing Dash components as html?

I am trying to implement a Dash version of the DivIcon component. One of its arguments is of the type String|HTMLElement. Hence, if i pass it an html string, the html will be rendered as intended. However, i would rather pass it Dash components (this would be more user friendly).

As a starting point, i tried passing the components via the children property of the Dash component, and then reassigning it in the JavaScript layer, i.e. something like

render() {
    const nProps = Object.assign({}, this.props, {"children": null});
    nProps.icon = new L.DivIcon({options:{html:this.props.children}});
    return <LeafletMarker {...nProps}/>

But (unsurprisingly) that does not work. Is there any way to achieve this behavior in Dash?

Do you, @chriddyp, know if this kind of use case is possible with the current version of Dash?

Unfortunately it’s not available by default.

However, components get serialized as json and so in theory you could transform that json into a react component call. In other words, think about children as if it is just some nested object / dictionary property. It has keys “namespace”, “type”, and “props”
There are a few limitations to this:

  • You won’t be able to update or observe the rendered components via callbacks. Dash introspects/crawls children to do this, it won’t crawl through any other component hierarchy
  • To handle nested components, you’ll need to crawl / recurse through the objects yourself and render them
  • Children may come to you, the component, as an already-rendered React element instead of its JSON representation. Im not sure here, this has changed a couple of times over the years. If it’s a rendered component, that’ll be harder to extract the properties from but you may be able to just render it directly. However, there is also this prop called something like _private_dash_layout (i’m on my phone and so i don’t remember exactly) that might contain the component in json form. Check out the source of the Tabs component, I believe that uses this property. Beware, this is a private property and so we may change it at any time without advance notice.
1 Like

Thanks for the elaborate answer! I ended up with the following approach,

  • Pass the objects from Dash via the children property to the JS layer
  • Create a new div element in JS, and assign the objects as children of this div with the rendering carried out via ReactDOM.createPortal

It feels a bit hacky, but at least it works :slight_smile:

1 Like