Access HTML element inside Div widget

Hey all,

I was wondering whether I can access – on the JS side – HTML elements that are embedded within a Div widget. For instance, consider the following example:

from bokeh.document import Document
from bokeh.embed import file_html
from bokeh.events import ButtonClick
from bokeh.models import Button, CustomJS, Div
from bokeh.layouts import layout
from bokeh.resources import INLINE
from bokeh.util.browser import view

mydiv = Div(text='<iframe id="myiframe"></iframe>', name='mydiv')

mybutton = Button(label='Click')
mybutton.js_on_event(ButtonClick,
                     CustomJS(code="debugger; //I'd like to access #myiframe from here"))

doc = Document()
doc.add_root(layout([[mybutton], [mydiv]]))

with open('test.html', 'w') as f:
    f.write(file_html(doc, INLINE))
view('test.html')

In the JS callback I would like to access the iframe HTML element. The prototypical document.getElementById('myiframe') does not work, presumably because of the shadowRoot structure created by Bokeh.

I know that there are other solutions e.g. using html templates, but I’m specifically interested in this setup and also specifically whether there is a more elegant version other than climbing down the entire nested (shadowRoot) tree using something like document.querySelector('div').children[0].shadowRoot.querySelectorAll('.bk-Row')[1].shadowRoot.querySelector('.bk-Div').shadowRoot.querySelector('#myiframe')

1 Like

climbing down the entire nested (shadowRoot) tree

There may be a more concise or “better” way to express the query above (I’m not sure offhand) but I did want to mention generally that those standard JavaScript DOM APIs are the correct place to be looking. Bokeh does not expose and different API of its own (mostly because it would be duplicative of the JS APIs and it’s not clear what benefit there would be)

Hi Bryan, thanks a lot for your response, much appreciated - this is the way to go then!

My (naive) reasoning was that since Bokeh also builds the DOM tree, there might be a built-in option to automatically generate a “native” Javascript DOM pointer to a Bokeh component, such that instead of the long querySelector chain one could use something like mydiv.dom. However, I have no idea how feasible this is.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.