Delay in seeing objects previously stored to Bokeh server

I decided a couple days ago to finally learn how to use Bokeh server. The following gist creates a simple form where I can select the number and type of plots to display in a GridPlot:

The initial state displays no plots. That’s good. I can select different numbers and types and see the changes. That’s good.

However, the “reset” button, which just sets the Select widgets to their initial values and then updates the plot, requires multiple clicks to work. Most of the time, the first click does nothing, the second click sets the n_plots Select widget to 0, and the third click finally gets rid of the graphs. Sometimes I have to click twice just to get the Select widget to reset. Sometimes the graphs go away but the toolbar doesn’t. If I set the polling interval to the default of 0.5, I usually have to click 4 times. If I set it much lower, I usually have to click 2-3 times. A few times I’ve had to click the thing six times to get it to fully reset.

I’m at a loss. What am I missing?

I’ve been exploring this further and am just getting more confused :slight_smile: My reset button callback is set to call self.reset_menu. When I click that button in the browser, as I’ve said, I see no change. Typically, the first click does nothing. The second click resets the select box to 0 but the URL still shows ?plot_type=Bars&n_plots={n} where {n} is the number I selected previous to resetting. The third click changes that to n_plots=0 but either leaves the graph in place or just leaves the toolbar.The fourth or fifth click finishes the reset.

On the python side, if I assign a new value to self.n_plot_select.value, and then call self.menu_submit, I can confirm that the new plots are in fact assigned as children of self.plot.children (self.plot being a GridPlot). And then I call self.menu_reset - just once - I can confirm that self.plot.children == [[None]] and self.plot.toolbar_location == None, just as they should be. So the python side is working fine, but for some reason those changes aren’t getting reflected in the browser.

I’d appreciate any ideas/advice anyone could give me.

···

On Thursday, April 23, 2015 at 7:23:21 AM UTC-4, Schaun Wheeler wrote:

I decided a couple days ago to finally learn how to use Bokeh server. The following gist creates a simple form where I can select the number and type of plots to display in a GridPlot:

https://gist.github.com/schaunwheeler/c560b634076d745cbba2

The initial state displays no plots. That’s good. I can select different numbers and types and see the changes. That’s good.

However, the “reset” button, which just sets the Select widgets to their initial values and then updates the plot, requires multiple clicks to work. Most of the time, the first click does nothing, the second click sets the n_plots Select widget to 0, and the third click finally gets rid of the graphs. Sometimes I have to click twice just to get the Select widget to reset. Sometimes the graphs go away but the toolbar doesn’t. If I set the polling interval to the default of 0.5, I usually have to click 4 times. If I set it much lower, I usually have to click 2-3 times. A few times I’ve had to click the thing six times to get it to fully reset.

I’m at a loss. What am I missing?

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app_simple.py
https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app.py

I’m not sure why your example isn’t working but I would suggest looking at the above 2 examples for embedding applications directly into the bokeh server. I think we are probably doing something wrong with the poll document approach - when we poll we get all the objects from the server every time, and to bokeh it looks like we’re changing every property of every object all the time.

···

On Sat, Apr 25, 2015 at 9:59 PM, Schaun Wheeler [email protected] wrote:

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

https://gist.github.com/schaunwheeler/db994b9828d851d92c81

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/5e779ed6-3586-4651-86c6-113f822e0d2e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Thanks, Hugo. I’d looked at those examples earlier but, being new to Bokeh server, they intimidated me :slight_smile: I was hoping to start simple and work up. Looks like I need to jump into them tomorrow.

With that in mind: could you (or anyone else on this list) give me a quick explanation of what purpose bokeh.properties.Instance serves? I know the docstrings say that Instance is “for references to other Models in the object graph”, but I don’t really understand what that means. Are all the calls to Instance in stock_app.py just for validating inputs during the StockApp.create call?

···

On Sunday, April 26, 2015 at 4:29:21 PM UTC-4, Hugo Shi wrote:

https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app_simple.py
https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app.py

I’m not sure why your example isn’t working but I would suggest looking at the above 2 examples for embedding applications directly into the bokeh server. I think we are probably doing something wrong with the poll document approach - when we poll we get all the objects from the server every time, and to bokeh it looks like we’re changing every property of every object all the time.

On Sat, Apr 25, 2015 at 9:59 PM, Schaun Wheeler [email protected] wrote:

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

https://gist.github.com/schaunwheeler/db994b9828d851d92c81

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/5e779ed6-3586-4651-86c6-113f822e0d2e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Bokeh has class level property validation - so what we do is allow you to define properties on classes

class TestApp(PlotObject):

width = Int()

height = Int()

plot = Instance(Plot)

Then if you assign width/height to the object, bokeh will make sure they are ints you are assigning, and if you assign something to Plot, bokeh will make sure it is a Plot instance.

anyways - I think the simpleapp example is easier (or at least it should be, if not, then we should fix simple app method so that it is indeed simpler) if you can fit your app into what it allows you to do

···

On Sun, Apr 26, 2015 at 7:31 PM, Schaun Wheeler [email protected] wrote:

Thanks, Hugo. I’d looked at those examples earlier but, being new to Bokeh server, they intimidated me :slight_smile: I was hoping to start simple and work up. Looks like I need to jump into them tomorrow.

With that in mind: could you (or anyone else on this list) give me a quick explanation of what purpose bokeh.properties.Instance serves? I know the docstrings say that Instance is “for references to other Models in the object graph”, but I don’t really understand what that means. Are all the calls to Instance in stock_app.py just for validating inputs during the StockApp.create call?

On Sunday, April 26, 2015 at 4:29:21 PM UTC-4, Hugo Shi wrote:

https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app_simple.py
https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app.py

I’m not sure why your example isn’t working but I would suggest looking at the above 2 examples for embedding applications directly into the bokeh server. I think we are probably doing something wrong with the poll document approach - when we poll we get all the objects from the server every time, and to bokeh it looks like we’re changing every property of every object all the time.

On Sat, Apr 25, 2015 at 9:59 PM, Schaun Wheeler [email protected] wrote:

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

https://gist.github.com/schaunwheeler/db994b9828d851d92c81

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/5e779ed6-3586-4651-86c6-113f822e0d2e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/ede218af-f044-4834-a234-c738cc3522b5%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Following Hugo’s advice, I changed my gist to follow (as closely as possible) stock_app.py:

I can get it to show up in the browser, but I can’t get the contents to change from the default setup that results from calling self.create, even though running the code in python does in fact push the changes to curdoc:

After running the code from the gist:

app = MenuChange.create()

menu should be closed and controls should have one button - and that is exactly what shows in the browser

state = curdoc().context.children[0].children[0].children[0].children

print ‘menu open: {menu_open}’.format(menu_open=app.menu_open)

print ‘mainrow contents:’

for s in state:

print ’ ', s

menu should be open and controls should have three buttons - but in the browser the menu is still closed and controls still have one button

app.toggle_menu()

state = curdoc().context.children[0].children[0].children[0].children

print ‘menu open: {menu_open}’.format(menu_open=app.menu_open)

print ‘mainrow contents:’

for s in state:

print ’ ', s

When I click the button repeatedly in the browser, every once in a while I can catch of glimpse of it actually making the expected changes, but then it reverts back almost instantly to the original state. How do I get my selections (or, in this case, my button clicks) to persist?

···

On Sunday, April 26, 2015 at 8:24:50 PM UTC-4, Hugo Shi wrote:

Bokeh has class level property validation - so what we do is allow you to define properties on classes

class TestApp(PlotObject):

width = Int()

height = Int()

plot = Instance(Plot)

Then if you assign width/height to the object, bokeh will make sure they are ints you are assigning, and if you assign something to Plot, bokeh will make sure it is a Plot instance.

anyways - I think the simpleapp example is easier (or at least it should be, if not, then we should fix simple app method so that it is indeed simpler) if you can fit your app into what it allows you to do

On Sun, Apr 26, 2015 at 7:31 PM, Schaun Wheeler [email protected] wrote:

Thanks, Hugo. I’d looked at those examples earlier but, being new to Bokeh server, they intimidated me :slight_smile: I was hoping to start simple and work up. Looks like I need to jump into them tomorrow.

With that in mind: could you (or anyone else on this list) give me a quick explanation of what purpose bokeh.properties.Instance serves? I know the docstrings say that Instance is “for references to other Models in the object graph”, but I don’t really understand what that means. Are all the calls to Instance in stock_app.py just for validating inputs during the StockApp.create call?

On Sunday, April 26, 2015 at 4:29:21 PM UTC-4, Hugo Shi wrote:

https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app_simple.py
https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app.py

I’m not sure why your example isn’t working but I would suggest looking at the above 2 examples for embedding applications directly into the bokeh server. I think we are probably doing something wrong with the poll document approach - when we poll we get all the objects from the server every time, and to bokeh it looks like we’re changing every property of every object all the time.

On Sat, Apr 25, 2015 at 9:59 PM, Schaun Wheeler [email protected] wrote:

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

https://gist.github.com/schaunwheeler/db994b9828d851d92c81

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/5e779ed6-3586-4651-86c6-113f822e0d2e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/ede218af-f044-4834-a234-c738cc3522b5%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi Shaun,

I’ve quickly tried to run your gist and actually seems that something odd is happening. Whenever you hit the button the action is being correctly handled by the action manager but, weirdly, it causes the app factory function. My best guess is that it’s a bug. Could you please open an issue on GH so we can triage and track that?

Trying to move forward on helping you get your example done. You can replace the menu_toggle button with a Select widget (with “ON”/'OFF" options) and then map the selection event to the same function.

Also, please note that there’s a small implementation detail in your example that makes the app not work properly. Basically you are creating your widgets (inputs) in the make_inputs method. This function also creates the lists to create your dynamic layout (mainrow_children_off, mainrow_children_on, etc…). Those are not widgets, just layout convenience attributes. When your app manages an event you are calling set_children that will use those attrs to build the layout. The problem is that, at this point, the reference to the objects that you have used to populate mainrow_* and friends have changed because of the server logic when serializing/deserializing objects to communicate with the client. So, in order to make things work as you’d expect you should create those attributes inside the set_children methods (or not create them at all as you are only using them there).

Here’s a modified version of your code that works on my local env (at least the on/off selection works):

from bokeh.properties import Instance, List, Bool, String, Any

from bokeh.models.widgets.buttons import Button

from bokeh.models.widgets import Select

from bokeh.models.widgets.markups import Paragraph

from bokeh.models.widgets.layouts import VBox, HBox, VBoxForm

from bokeh.server.app import bokeh_app

from bokeh.server.utils.plugins import object_page

from bokeh.plotting import curdoc

class MenuChange(VBox):

extra_generated_classes = [[“MenuChange”, “MenuChange”, “VBox”]]

jsmodel = “VBox”

layout boxes

mainrow_children_on = List(Any)

mainrow_children_off = List(Any)

otherrow_children_on = List(Instance(VBox))

otherrow_children_off = List(Instance(VBox))

mainrow = Instance(HBox)

otherrow = Instance(VBox)

input_box = Instance(VBoxForm)

paragraph = Instance(Paragraph)

menu_open = Bool(default=False)

inputs

menu_submit = Instance(Button)

menu_toggle = Instance(Button)

menu_reset = Instance(Button)

ticker = Instance(Select)

on_off = String(default=‘OFF’)

def init(self, *args, **kwargs):

super(MenuChange, self).init(*args, **kwargs)

@classmethod

def create(cls):

obj = cls()

obj.input_box = VBoxForm()

obj.mainrow = HBox()

obj.otherrow = VBox()

obj.make_inputs()

obj.set_children()

return obj

def make_inputs(self):

self.menu_submit = Button(label=‘Submit’, type=‘warning’)

self.menu_toggle = Button(label=‘Select plot criteria’, type=‘primary’)

self.menu_reset = Button(label=‘Reset’)

self.ticker = Select(

name=‘ticker1’,

value=‘OFF’,

options=[‘OFF’, ‘ON’]

)

self.paragraph = Paragraph()

def set_children(self):

self.children = [self.input_box]

self.input_box.children = [self.mainrow, self.otherrow]

if self.menu_open:

self.menu_toggle.label = ‘Cancel’

self.menu_toggle.type = ‘default’

self.paragraph.text = ‘Menu toggled on’

self.mainrow.children = [self.ticker, self.menu_submit, self.menu_toggle, self.menu_reset]

self.otherrow.children = [VBox(children=[self.paragraph])]

else:

self.menu_toggle.label = ‘Select plot criteria’

self.menu_toggle.type = ‘primary’

self.paragraph.text = ‘Menu toggled off’

self.mainrow.children = [self.ticker, self.menu_toggle]

self.otherrow.children = [VBox(children=[self.paragraph])]

curdoc().add(self)

def toggle_menu(self, *a, **k):

self.menu_open = not self.menu_open

self.set_children()

def submit_menu(self):

self.toggle_menu()

def reset_menu(self):

self.init()

def setup_events(self):

super(MenuChange, self).setup_events()

if self.menu_submit:

self.menu_submit.on_click(self.submit_menu)

if self.menu_reset:

self.menu_reset.on_click(self.reset_menu)

if self.ticker:

self.ticker.on_change(‘value’, self, ‘toggle_menu’)

@bokeh_app.route("/bokeh/menu_change/")

@object_page(“menu_change”)

def make_menu():

app = MenuChange.create()

return app

``

Thanks

Fabio

···

On Monday, April 27, 2015 at 7:33:43 PM UTC+2, Schaun Wheeler wrote:

Following Hugo’s advice, I changed my gist to follow (as closely as possible) stock_app.py:

https://gist.github.com/schaunwheeler/0a0b7f79018ed65d56aa

I can get it to show up in the browser, but I can’t get the contents to change from the default setup that results from calling self.create, even though running the code in python does in fact push the changes to curdoc:

After running the code from the gist:

app = MenuChange.create()

menu should be closed and controls should have one button - and that is exactly what shows in the browser

state = curdoc().context.children[0].children[0].children[0].children

print ‘menu open: {menu_open}’.format(menu_open=app.menu_open)

print ‘mainrow contents:’

for s in state:

print ’ ', s

menu should be open and controls should have three buttons - but in the browser the menu is still closed and controls still have one button

app.toggle_menu()

state = curdoc().context.children[0].children[0].children[0].children

print ‘menu open: {menu_open}’.format(menu_open=app.menu_open)

print ‘mainrow contents:’

for s in state:

print ’ ', s

When I click the button repeatedly in the browser, every once in a while I can catch of glimpse of it actually making the expected changes, but then it reverts back almost instantly to the original state. How do I get my selections (or, in this case, my button clicks) to persist?

On Sunday, April 26, 2015 at 8:24:50 PM UTC-4, Hugo Shi wrote:

Bokeh has class level property validation - so what we do is allow you to define properties on classes

class TestApp(PlotObject):

width = Int()

height = Int()

plot = Instance(Plot)

Then if you assign width/height to the object, bokeh will make sure they are ints you are assigning, and if you assign something to Plot, bokeh will make sure it is a Plot instance.

anyways - I think the simpleapp example is easier (or at least it should be, if not, then we should fix simple app method so that it is indeed simpler) if you can fit your app into what it allows you to do

On Sun, Apr 26, 2015 at 7:31 PM, Schaun Wheeler [email protected] wrote:

Thanks, Hugo. I’d looked at those examples earlier but, being new to Bokeh server, they intimidated me :slight_smile: I was hoping to start simple and work up. Looks like I need to jump into them tomorrow.

With that in mind: could you (or anyone else on this list) give me a quick explanation of what purpose bokeh.properties.Instance serves? I know the docstrings say that Instance is “for references to other Models in the object graph”, but I don’t really understand what that means. Are all the calls to Instance in stock_app.py just for validating inputs during the StockApp.create call?

On Sunday, April 26, 2015 at 4:29:21 PM UTC-4, Hugo Shi wrote:

https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app_simple.py
https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app.py

I’m not sure why your example isn’t working but I would suggest looking at the above 2 examples for embedding applications directly into the bokeh server. I think we are probably doing something wrong with the poll document approach - when we poll we get all the objects from the server every time, and to bokeh it looks like we’re changing every property of every object all the time.

On Sat, Apr 25, 2015 at 9:59 PM, Schaun Wheeler [email protected] wrote:

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

https://gist.github.com/schaunwheeler/db994b9828d851d92c81

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/5e779ed6-3586-4651-86c6-113f822e0d2e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/ede218af-f044-4834-a234-c738cc3522b5%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Thanks, Fabio! This was extremely helpful.

···

On Tuesday, May 5, 2015 at 10:20:48 AM UTC-4, Fabio Pliger wrote:

Hi Shaun,

I’ve quickly tried to run your gist and actually seems that something odd is happening. Whenever you hit the button the action is being correctly handled by the action manager but, weirdly, it causes the app factory function. My best guess is that it’s a bug. Could you please open an issue on GH so we can triage and track that?

Trying to move forward on helping you get your example done. You can replace the menu_toggle button with a Select widget (with “ON”/'OFF" options) and then map the selection event to the same function.

Also, please note that there’s a small implementation detail in your example that makes the app not work properly. Basically you are creating your widgets (inputs) in the make_inputs method. This function also creates the lists to create your dynamic layout (mainrow_children_off, mainrow_children_on, etc…). Those are not widgets, just layout convenience attributes. When your app manages an event you are calling set_children that will use those attrs to build the layout. The problem is that, at this point, the reference to the objects that you have used to populate mainrow_* and friends have changed because of the server logic when serializing/deserializing objects to communicate with the client. So, in order to make things work as you’d expect you should create those attributes inside the set_children methods (or not create them at all as you are only using them there).

Here’s a modified version of your code that works on my local env (at least the on/off selection works):

from bokeh.properties import Instance, List, Bool, String, Any

from bokeh.models.widgets.buttons import Button

from bokeh.models.widgets import Select

from bokeh.models.widgets.markups import Paragraph

from bokeh.models.widgets.layouts import VBox, HBox, VBoxForm

from bokeh.server.app import bokeh_app

from bokeh.server.utils.plugins import object_page

from bokeh.plotting import curdoc

class MenuChange(VBox):

extra_generated_classes = [[“MenuChange”, “MenuChange”, “VBox”]]

jsmodel = “VBox”

layout boxes

mainrow_children_on = List(Any)

mainrow_children_off = List(Any)

otherrow_children_on = List(Instance(VBox))

otherrow_children_off = List(Instance(VBox))

mainrow = Instance(HBox)

otherrow = Instance(VBox)

input_box = Instance(VBoxForm)

paragraph = Instance(Paragraph)

menu_open = Bool(default=False)

inputs

menu_submit = Instance(Button)

menu_toggle = Instance(Button)

menu_reset = Instance(Button)

ticker = Instance(Select)

on_off = String(default=‘OFF’)

def init(self, *args, **kwargs):

super(MenuChange, self).init(*args, **kwargs)

@classmethod

def create(cls):

obj = cls()

obj.input_box = VBoxForm()

obj.mainrow = HBox()

obj.otherrow = VBox()

obj.make_inputs()

obj.set_children()

return obj

def make_inputs(self):

self.menu_submit = Button(label=‘Submit’, type=‘warning’)

self.menu_toggle = Button(label=‘Select plot criteria’, type=‘primary’)

self.menu_reset = Button(label=‘Reset’)

self.ticker = Select(

name=‘ticker1’,

value=‘OFF’,

options=[‘OFF’, ‘ON’]

)

self.paragraph = Paragraph()

def set_children(self):

self.children = [self.input_box]

self.input_box.children = [self.mainrow, self.otherrow]

if self.menu_open:

self.menu_toggle.label = ‘Cancel’

self.menu_toggle.type = ‘default’

self.paragraph.text = ‘Menu toggled on’

self.mainrow.children = [self.ticker, self.menu_submit, self.menu_toggle, self.menu_reset]

self.otherrow.children = [VBox(children=[self.paragraph])]

else:

self.menu_toggle.label = ‘Select plot criteria’

self.menu_toggle.type = ‘primary’

self.paragraph.text = ‘Menu toggled off’

self.mainrow.children = [self.ticker, self.menu_toggle]

self.otherrow.children = [VBox(children=[self.paragraph])]

curdoc().add(self)

def toggle_menu(self, *a, **k):

self.menu_open = not self.menu_open

self.set_children()

def submit_menu(self):

self.toggle_menu()

def reset_menu(self):

self.init()

def setup_events(self):

super(MenuChange, self).setup_events()

if self.menu_submit:

self.menu_submit.on_click(self.submit_menu)

if self.menu_reset:

self.menu_reset.on_click(self.reset_menu)

if self.ticker:

self.ticker.on_change(‘value’, self, ‘toggle_menu’)

@bokeh_app.route("/bokeh/menu_change/")

@object_page(“menu_change”)

def make_menu():

app = MenuChange.create()

return app

``

Thanks

Fabio

On Monday, April 27, 2015 at 7:33:43 PM UTC+2, Schaun Wheeler wrote:

Following Hugo’s advice, I changed my gist to follow (as closely as possible) stock_app.py:

https://gist.github.com/schaunwheeler/0a0b7f79018ed65d56aa

I can get it to show up in the browser, but I can’t get the contents to change from the default setup that results from calling self.create, even though running the code in python does in fact push the changes to curdoc:

After running the code from the gist:

app = MenuChange.create()

menu should be closed and controls should have one button - and that is exactly what shows in the browser

state = curdoc().context.children[0].children[0].children[0].children

print ‘menu open: {menu_open}’.format(menu_open=app.menu_open)

print ‘mainrow contents:’

for s in state:

print ’ ', s

menu should be open and controls should have three buttons - but in the browser the menu is still closed and controls still have one button

app.toggle_menu()

state = curdoc().context.children[0].children[0].children[0].children

print ‘menu open: {menu_open}’.format(menu_open=app.menu_open)

print ‘mainrow contents:’

for s in state:

print ’ ', s

When I click the button repeatedly in the browser, every once in a while I can catch of glimpse of it actually making the expected changes, but then it reverts back almost instantly to the original state. How do I get my selections (or, in this case, my button clicks) to persist?

On Sunday, April 26, 2015 at 8:24:50 PM UTC-4, Hugo Shi wrote:

Bokeh has class level property validation - so what we do is allow you to define properties on classes

class TestApp(PlotObject):

width = Int()

height = Int()

plot = Instance(Plot)

Then if you assign width/height to the object, bokeh will make sure they are ints you are assigning, and if you assign something to Plot, bokeh will make sure it is a Plot instance.

anyways - I think the simpleapp example is easier (or at least it should be, if not, then we should fix simple app method so that it is indeed simpler) if you can fit your app into what it allows you to do

On Sun, Apr 26, 2015 at 7:31 PM, Schaun Wheeler [email protected] wrote:

Thanks, Hugo. I’d looked at those examples earlier but, being new to Bokeh server, they intimidated me :slight_smile: I was hoping to start simple and work up. Looks like I need to jump into them tomorrow.

With that in mind: could you (or anyone else on this list) give me a quick explanation of what purpose bokeh.properties.Instance serves? I know the docstrings say that Instance is “for references to other Models in the object graph”, but I don’t really understand what that means. Are all the calls to Instance in stock_app.py just for validating inputs during the StockApp.create call?

On Sunday, April 26, 2015 at 4:29:21 PM UTC-4, Hugo Shi wrote:

https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app_simple.py
https://github.com/bokeh/bokeh/blob/master/examples/app/stock_applet/stock_app.py

I’m not sure why your example isn’t working but I would suggest looking at the above 2 examples for embedding applications directly into the bokeh server. I think we are probably doing something wrong with the poll document approach - when we poll we get all the objects from the server every time, and to bokeh it looks like we’re changing every property of every object all the time.

On Sat, Apr 25, 2015 at 9:59 PM, Schaun Wheeler [email protected] wrote:

Still working on this. It seems this is an issue with Bokeh server not fully…or at least not immediately…reflecting changes that are made to the document. I created a new gist:

https://gist.github.com/schaunwheeler/db994b9828d851d92c81

This one creates an expandable menu: it starts off with a single “Select plot criteria” button in a VBox, and if I click that button, it adds all of the other widgets as children of that same VBox, and changes the submit button to say “Cancel”. Click on the cancel, and the widgets are all removed from the parent and the label is changed back to “Select plot criteria”.

When I click the button, the button label changes but nothing else happens. If I do nothing else but manually refresh the page in my browser, all of the expected changes are then displayed. When I click the button again, the button label again changes, but the menu isn’t retracted. As before, manually refreshing the page produces the expected behavior. Every once in a while (maybe 1 out of 10 times), I get the expected behavior on first click.

It seems that bokeh server updates the page in the browser before the objects from the python side have been fully saved, and therefore the page displayed in the browser reflects only part of the changes, and waiting just a second longer and then refreshing the page makes it take a second look at the document, at which point it sees the full set of changes and reflects them in the browser.

Can anyone confirm if this is a bug? If so, I’ll submit a Github issue.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/5e779ed6-3586-4651-86c6-113f822e0d2e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/ede218af-f044-4834-a234-c738cc3522b5%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.