Hello @optmat, here is a workaround by using panel.
The code you show is perfectly legit and something I would have also done before panel. But I think the patterns that panel offer will make your life much easier (in addition to solve this specific issue).
This is how it looks (this is code for a notebook).
import panel as pn
import numpy as np
import holoviews as hv
pn.extension()
def hv_graph(edge_color, node_color):
node_indices = np.arange(2, dtype=np.int32)
source = np.zeros(2, dtype=np.int32)
target = node_indices
graph = hv.Graph(((source, target),)).opts(edge_color=edge_color, node_color=node_color)
return graph
h = pn.interact(hv_graph,edge_color=['green','black'],node_color=['green','black'])
h.save('dmap.html',embed=True)
h
Note that to specify embed=True is very important since it will precalculate all the states of your app so that the html has all what it needs to be dynamic (without a Python server) ; see embedding and save documentation.
To expect that hv.save or the save method from panel gives you the same interactivity with or without a running Python server is very natural from the user perspective but in reality is asking a lot (given that you could put any kind of calculations inside the hv_graph function). For this to work, it’s better to have a limited number of states (the default is limited to 1000 states).
In your case though, if all you do is to expose Bokeh options, there would certainly be a more efficient way than precalculating every state, but I guess this would require to integrate and interact with bokehjs directly and write some html and js code.