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 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.