Hi folks,
I have bokeh application with around 6 tabs and 3-4 interactive plots under each tab. These plots have a lot of datapoints and take time to plot. Loading all plots in one shot is fairly slow, so I want to use flask to draw one tab at a time:
index.html
<html>
<head>
<script type="text/javascript">
function openvtab(evt, tabname) {
fetch('/tabs/' + tabname)
.then(response => response.text())
.then(html => {
console.log(document.getElementById('tabitems'));
document.getElementById('tabitems').innerHTML = html
})
}
</script>
</head>
<body>
<div class="mytab" style="width:135px">
<button class="button-active tablink" onclick="openvtab(event, 'a1')">A1</button>
<button class="button-inactive tablink" onclick="openvtab(event, 'b1')">B1</button>
</div>
<div style="margin-left:140px">
<div id="tabitems" class="vani-tab" style="display:block"></div>
</div>
</body>
</html>
app/routes.py
app_html = """
{{bokeh_script|safe}}
"""
bokeh_process = subprocess.Popen(
['python', '-m', 'bokeh', 'serve', '--address','10.40.14.5', '--port', '5002', '--allow-websocket-origin=10.40.14.5:5000', 'dashboard'], stdout=subprocess.PIPE)
@atexit.register
def kill_bokeh_server():
bokeh_process.kill()
@app.route('/')
def index():
return render_template('index.html', resource=CDN.render().strip())
@app.route('/tabs/<string:tabname>')
def rendertab(tabname):
app.logger.info('in '+tabname)
bokeh_script = server_document(url='http://10.40.14.5:5002/dashboard', arguments=dict(tabname=tabname))
return render_template_string(app_html, bokeh_script = bokeh_script)
Now looking at the returned html on the browser, I see that the script is downloaded and expanded for each of the tabs, but is not executed (so doesn’t expand to actual chart). This is expected because innerHTML writes it as a string. However appendChild itself fails because the return of render_template_string is a string and not a JS object.
What’s the best way to handle this?