Bokeh Confirm Dialog

Hi,

I would like to use a Button widget with a confirm dialog (i.e. “do you really want to do this ? YES/NO”).

Based on the user’s choice in the confirm dialog, I would like to get a callback in the Python code similar to a typical “on_click” event.

So far I have tried and failed with the following approaches:

(1) The Dialog widget [1] appears to do exactly what I want but I can’t get it to work.

I get the JS error “String property ‘content’ given invalid value: Row(7437aac2-…)” with the following code:

#!/usr/bin/env python

import numpy as np

#from bokeh.io import vplot

from bokeh.layouts import column

from bokeh.layouts import row, widgetbox

from bokeh.models import CustomJS, Slider, Paragraph, Dialog, Button

from bokeh.plotting import figure, output_file, show, ColumnDataSource

x = np.linspace(0, 10, 500)

y = np.sin(x)

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)

plot.line(‘x’, ‘y’, source=source, line_width=3, line_alpha=0.6)

descr_box = Paragraph(text=‘content loading…’)

btn_close_loading = Button(label=‘Close Loading’)

dialog_loading = Dialog(

title=‘loading’, content=row(descr_box), name=‘loading_dialog’,

buttons=[btn_close_loading], visible=True)

layout = column(

dialog_loading,

plot,

widgetbox(btn_close_loading),

)

output_file(“slider.html”, title=“slider.py example”)

show(layout)

``

(2) I tried and failed to use a Javascript callback function that changes a ColumnDataSource object like it is described in the bokeh documentation [2].

Within the JavaScript code I emit a ‘change’ trigger to be able to react on it from within the Python code.

The idea is that while running the bokeh server, I can add an ‘on_change’ callback function to the data source allowing me to get the result of the JavaScript dialog.

While the Javascript Dialog appears as soon as the button is pressed, I never get a callback for the changed ColumnDataSource. In addition, as soon as I add a CustomJS callback

parameter to the Toggle button, the “on_click” callback is no longer working. Neither are any other Python callbacks:

#!/usr/bin/env python

``

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

x=[0]

y=x

confirmResponse = ColumnDataSource(data=dict(answer=x, y=y))

callback = CustomJS(args=dict(confirmResponse=confirmResponse), code="""

	// get data source from Callback args

    var data = confirmResponse.get('data');

    data['answer']

var confirmResponse = confirm("Really do it?")

if (confirmResponse) {

	data['answer']=1;

} else {

	data['answer']=0;

}

// trigger update of data source

    confirmResponse.trigger('change');

""")

def toggle_handler(active):

print("toggle_handler: %s, confirmResponse: %s" % (active,x))

toggle = Toggle(label=“Toggle button”, button_type=“success”, callback=callback)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

confirmResponse.properties()

confirmResponse.on_change(‘data’, default_handler)

confirmResponse.on_change(‘name’, default_handler)

confirmResponse.on_change(‘selected’, default_handler)

confirmResponse.on_change(‘tags’, default_handler)

confirmResponse.on_change(‘change’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

(3) I tried to create my own dialog by just adding a new button from within an “on_click” event. While this works, I can no longer remove that button from the WidgetBox. If I try, I

get the error “UnboundLocalError: local variable ‘toggle1’ referenced before assignment”.

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

toggle1=None

def toggle_handler(active):

print("toggle_handler: %s" % (active))

if active:

    toggle.label = 'start'

    toggle.disabled=True

    toggle1 = Toggle(label="Another Toggle button", button_type="success")

    box.children.append(toggle1)

else:

    toggle.label = 'stop'

    toggle.disabled=False

    if (toggle1 is not None):

        box.children.remove(toggle1)

        toggle1=None

toggle = Toggle(label=“Toggle button”, button_type=“success”)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

``

So, after all of these approaches have failed, is there any way to create something like a confirm dialog with Bokeh at all ?

Thanks,

Stefan

[1] http://bokeh.pydata.org/en/latest/docs/reference/models/widgets.dialogs.html

[2] JavaScript callbacks — Bokeh 2.4.2 Documentation

Hi,

The dialog widget has been broken for a long time, and there was no reports or questions about it that entire time, so it was decided to remove it, since there is not really anyone who would be able to work on fixing it any time soon. It will not be present in 0.12.4 or later releases. I'd say the best option for a confirm dialog is to make a bokeh extension that is a thin wrapper around any of the many JS libraries for dialogs. Here are the docs and several full examples for building Bokeh extensions:

  http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html

Thanks,

Bryan

···

On Oct 28, 2016, at 2:35 PM, Stefan <[email protected]> wrote:

Hi,

I would like to use a Button widget with a confirm dialog (i.e. "do you really want to do this ? YES/NO").
Based on the user's choice in the confirm dialog, I would like to get a callback in the Python code similar to a typical "on_click" event.
So far I have tried and failed with the following approaches:

(1) The Dialog widget [1] appears to do exactly what I want but I can't get it to work.
I get the JS error "String property 'content' given invalid value: Row(7437aac2-....)" with the following code:

#!/usr/bin/env python
import numpy as np

#from bokeh.io import vplot
from bokeh.layouts import column
from bokeh.layouts import row, widgetbox
from bokeh.models import CustomJS, Slider, Paragraph, Dialog, Button
from bokeh.plotting import figure, output_file, show, ColumnDataSource

x = np.linspace(0, 10, 500)
y = np.sin(x)

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)

plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

descr_box = Paragraph(text='content loading...')

btn_close_loading = Button(label='Close Loading')
dialog_loading = Dialog(
    title='loading', content=row(descr_box), name='loading_dialog',
    buttons=[btn_close_loading], visible=True)

layout = column(
    dialog_loading,
    plot,
    widgetbox(btn_close_loading),
)

output_file("slider.html", title="slider.py example")

show(layout)

(2) I tried and failed to use a Javascript callback function that changes a ColumnDataSource object like it is described in the bokeh documentation [2].
Within the JavaScript code I emit a 'change' trigger to be able to react on it from within the Python code.
The idea is that while running the bokeh server, I can add an 'on_change' callback function to the data source allowing me to get the result of the JavaScript dialog.
While the Javascript Dialog appears as soon as the button is pressed, I never get a callback for the changed ColumnDataSource. In addition, as soon as I add a CustomJS callback
parameter to the Toggle button, the "on_click" callback is no longer working. Neither are any other Python callbacks:

#!/usr/bin/env python

from __future__ import print_function

from bokeh.util.browser import view
from bokeh.document import Document
from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle
from bokeh.models.widgets import RadioButtonGroup
from bokeh.models.widgets.dialogs import Dialog
from bokeh.models.widgets.buttons import Button
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.layouts import widgetbox

from bokeh.client import push_session

x=[0]
y=x

confirmResponse = ColumnDataSource(data=dict(answer=x, y=y))
callback = CustomJS(args=dict(confirmResponse=confirmResponse), code="""
      // get data source from Callback args
        var data = confirmResponse.get('data');
        data['answer']

  var confirmResponse = confirm("Really do it?")
  if (confirmResponse) {
    data['answer']=1;
  } else {
    data['answer']=0;
  }
  
  // trigger update of data source
        confirmResponse.trigger('change');
    """)

def toggle_handler(active):
    print("toggle_handler: %s, confirmResponse: %s" % (active,x))

toggle = Toggle(label="Toggle button", button_type="success", callback=callback)
toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):
    print ("default handler with attribute %s" %attrname, old, new)

# toggle.properties()
toggle.on_change('active', default_handler)
toggle.on_change('clicks', default_handler)
toggle.on_change('value', default_handler)
toggle.on_change('disabled', default_handler)

# confirmResponse.properties()
confirmResponse.on_change('data', default_handler)
confirmResponse.on_change('name', default_handler)
confirmResponse.on_change('selected', default_handler)
confirmResponse.on_change('tags', default_handler)
confirmResponse.on_change('change', default_handler)

box = widgetbox(children=[toggle])

document = Document()
document.add_root(box)
session = push_session(document)
session.show()

if __name__ == "__main__":
    session.loop_until_closed()

(3) I tried to create my own dialog by just adding a new button from within an "on_click" event. While this works, I can no longer remove that button from the WidgetBox. If I try, I
get the error "UnboundLocalError: local variable 'toggle1' referenced before assignment".

#!/usr/bin/env python

from __future__ import print_function

from bokeh.util.browser import view
from bokeh.document import Document
from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle
from bokeh.models.widgets import RadioButtonGroup
from bokeh.models.widgets.dialogs import Dialog
from bokeh.models.widgets.buttons import Button
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.layouts import widgetbox

from bokeh.client import push_session

toggle1=None

def toggle_handler(active):
    print("toggle_handler: %s" % (active))
    if active:
        toggle.label = 'start'
        toggle.disabled=True
        toggle1 = Toggle(label="Another Toggle button", button_type="success")
        box.children.append(toggle1)
    else:
        toggle.label = 'stop'
        toggle.disabled=False
        if (toggle1 is not None):
            box.children.remove(toggle1)
            toggle1=None

toggle = Toggle(label="Toggle button", button_type="success")
toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):
    print ("default handler with attribute %s" %attrname, old, new)

# toggle.properties()
toggle.on_change('active', default_handler)
toggle.on_change('clicks', default_handler)
toggle.on_change('value', default_handler)
toggle.on_change('disabled', default_handler)

box = widgetbox(children=[toggle])

document = Document()
document.add_root(box)
session = push_session(document)
session.show()

if __name__ == "__main__":
    session.loop_until_closed()

So, after all of these approaches have failed, is there *any* way to create something like a confirm dialog with Bokeh at all ?

Thanks,
Stefan

[1] http://bokeh.pydata.org/en/latest/docs/reference/models/widgets.dialogs.html
[2] http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-widgets

--
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/2e0aad68-0193-4911-8218-d0bd004b5885%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

What about approach number (3) ?
Shouldn’t it be possible to just hide/remove a button from an “on_click” callback ?

Thanks,

Stefan

···

Am Freitag, 28. Oktober 2016 21:51:02 UTC+2 schrieb Bryan Van de ven:

Hi,

The dialog widget has been broken for a long time, and there was no reports or questions about it that entire time, so it was decided to remove it, since there is not really anyone who would be able to work on fixing it any time soon. It will not be present in 0.12.4 or later releases. I’d say the best option for a confirm dialog is to make a bokeh extension that is a thin wrapper around any of the many JS libraries for dialogs. Here are the docs and several full examples for building Bokeh extensions:

    [http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html](http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html)

Thanks,

Bryan

On Oct 28, 2016, at 2:35 PM, Stefan [email protected] wrote:

Hi,

I would like to use a Button widget with a confirm dialog (i.e. “do you really want to do this ? YES/NO”).

Based on the user’s choice in the confirm dialog, I would like to get a callback in the Python code similar to a typical “on_click” event.

So far I have tried and failed with the following approaches:

(1) The Dialog widget [1] appears to do exactly what I want but I can’t get it to work.

I get the JS error “String property ‘content’ given invalid value: Row(7437aac2-…)” with the following code:

#!/usr/bin/env python

import numpy as np

#from bokeh.io import vplot

from bokeh.layouts import column

from bokeh.layouts import row, widgetbox

from bokeh.models import CustomJS, Slider, Paragraph, Dialog, Button

from bokeh.plotting import figure, output_file, show, ColumnDataSource

x = np.linspace(0, 10, 500)

y = np.sin(x)

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)

plot.line(‘x’, ‘y’, source=source, line_width=3, line_alpha=0.6)

descr_box = Paragraph(text=‘content loading…’)

btn_close_loading = Button(label=‘Close Loading’)

dialog_loading = Dialog(

title='loading', content=row(descr_box), name='loading_dialog',
buttons=[btn_close_loading], visible=True)

layout = column(

dialog_loading,
plot,
widgetbox(btn_close_loading),

)

output_file(“slider.html”, title=“slider.py example”)

show(layout)

(2) I tried and failed to use a Javascript callback function that changes a ColumnDataSource object like it is described in the bokeh documentation [2].

Within the JavaScript code I emit a ‘change’ trigger to be able to react on it from within the Python code.

The idea is that while running the bokeh server, I can add an ‘on_change’ callback function to the data source allowing me to get the result of the JavaScript dialog.

While the Javascript Dialog appears as soon as the button is pressed, I never get a callback for the changed ColumnDataSource. In addition, as soon as I add a CustomJS callback

parameter to the Toggle button, the “on_click” callback is no longer working. Neither are any other Python callbacks:

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

x=[0]

y=x

confirmResponse = ColumnDataSource(data=dict(answer=x, y=y))

callback = CustomJS(args=dict(confirmResponse=confirmResponse), code=“”"

        // get data source from Callback args
    var data = confirmResponse.get('data');
    data['answer']
    var confirmResponse = confirm("Really do it?")
    if (confirmResponse) {
            data['answer']=1;
    } else {
            data['answer']=0;
    }
    // trigger update of data source
    confirmResponse.trigger('change');        
""")

def toggle_handler(active):

print("toggle_handler: %s, confirmResponse: %s" % (active,x))

toggle = Toggle(label=“Toggle button”, button_type=“success”, callback=callback)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

confirmResponse.properties()

confirmResponse.on_change(‘data’, default_handler)

confirmResponse.on_change(‘name’, default_handler)

confirmResponse.on_change(‘selected’, default_handler)

confirmResponse.on_change(‘tags’, default_handler)

confirmResponse.on_change(‘change’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

(3) I tried to create my own dialog by just adding a new button from within an “on_click” event. While this works, I can no longer remove that button from the WidgetBox. If I try, I

get the error “UnboundLocalError: local variable ‘toggle1’ referenced before assignment”.

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

toggle1=None

def toggle_handler(active):

print("toggle_handler: %s" % (active))
if active:
    toggle.label = 'start'
    toggle.disabled=True
    toggle1 = Toggle(label="Another Toggle button", button_type="success")
    box.children.append(toggle1)
else:
    toggle.label = 'stop'
    toggle.disabled=False
    if (toggle1 is not None):
        box.children.remove(toggle1)
        toggle1=None

toggle = Toggle(label=“Toggle button”, button_type=“success”)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

So, after all of these approaches have failed, is there any way to create something like a confirm dialog with Bokeh at all ?

Thanks,

Stefan

[1] http://bokeh.pydata.org/en/latest/docs/reference/models/widgets.dialogs.html

[2] http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-widgets


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/2e0aad68-0193-4911-8218-d0bd004b5885%40continuum.io.

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

You need to add “global toggle1” to the top of the callback to use the toggle1 variable in that way.

Thanks,

Bryan

···

On Oct 29, 2016, at 05:13, [email protected] wrote:

What about approach number (3) ?
Shouldn’t it be possible to just hide/remove a button from an “on_click” callback ?

Thanks,

Stefan

Am Freitag, 28. Oktober 2016 21:51:02 UTC+2 schrieb Bryan Van de ven:

Hi,

The dialog widget has been broken for a long time, and there was no reports or questions about it that entire time, so it was decided to remove it, since there is not really anyone who would be able to work on fixing it any time soon. It will not be present in 0.12.4 or later releases. I’d say the best option for a confirm dialog is to make a bokeh extension that is a thin wrapper around any of the many JS libraries for dialogs. Here are the docs and several full examples for building Bokeh extensions:

    [http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html](http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html)

Thanks,

Bryan

On Oct 28, 2016, at 2:35 PM, Stefan [email protected] wrote:

Hi,

I would like to use a Button widget with a confirm dialog (i.e. “do you really want to do this ? YES/NO”).

Based on the user’s choice in the confirm dialog, I would like to get a callback in the Python code similar to a typical “on_click” event.

So far I have tried and failed with the following approaches:

(1) The Dialog widget [1] appears to do exactly what I want but I can’t get it to work.

I get the JS error “String property ‘content’ given invalid value: Row(7437aac2-…)” with the following code:

#!/usr/bin/env python

import numpy as np

#from bokeh.io import vplot

from bokeh.layouts import column

from bokeh.layouts import row, widgetbox

from bokeh.models import CustomJS, Slider, Paragraph, Dialog, Button

from bokeh.plotting import figure, output_file, show, ColumnDataSource

x = np.linspace(0, 10, 500)

y = np.sin(x)

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)

plot.line(‘x’, ‘y’, source=source, line_width=3, line_alpha=0.6)

descr_box = Paragraph(text=‘content loading…’)

btn_close_loading = Button(label=‘Close Loading’)

dialog_loading = Dialog(

title='loading', content=row(descr_box), name='loading_dialog',
buttons=[btn_close_loading], visible=True)

layout = column(

dialog_loading,
plot,
widgetbox(btn_close_loading),

)

output_file(“slider.html”, title=“slider.py example”)

show(layout)

(2) I tried and failed to use a Javascript callback function that changes a ColumnDataSource object like it is described in the bokeh documentation [2].

Within the JavaScript code I emit a ‘change’ trigger to be able to react on it from within the Python code.

The idea is that while running the bokeh server, I can add an ‘on_change’ callback function to the data source allowing me to get the result of the JavaScript dialog.

While the Javascript Dialog appears as soon as the button is pressed, I never get a callback for the changed ColumnDataSource. In addition, as soon as I add a CustomJS callback

parameter to the Toggle button, the “on_click” callback is no longer working. Neither are any other Python callbacks:

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

x=[0]

y=x

confirmResponse = ColumnDataSource(data=dict(answer=x, y=y))

callback = CustomJS(args=dict(confirmResponse=confirmResponse), code=“”"

        // get data source from Callback args
    var data = confirmResponse.get('data');
    data['answer']
    var confirmResponse = confirm("Really do it?")
    if (confirmResponse) {
            data['answer']=1;
    } else {
            data['answer']=0;
    }
    // trigger update of data source
    confirmResponse.trigger('change');        
""")

def toggle_handler(active):

print("toggle_handler: %s, confirmResponse: %s" % (active,x))

toggle = Toggle(label=“Toggle button”, button_type=“success”, callback=callback)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

confirmResponse.properties()

confirmResponse.on_change(‘data’, default_handler)

confirmResponse.on_change(‘name’, default_handler)

confirmResponse.on_change(‘selected’, default_handler)

confirmResponse.on_change(‘tags’, default_handler)

confirmResponse.on_change(‘change’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

(3) I tried to create my own dialog by just adding a new button from within an “on_click” event. While this works, I can no longer remove that button from the WidgetBox. If I try, I

get the error “UnboundLocalError: local variable ‘toggle1’ referenced before assignment”.

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

toggle1=None

def toggle_handler(active):

print("toggle_handler: %s" % (active))
if active:
    toggle.label = 'start'
    toggle.disabled=True
    toggle1 = Toggle(label="Another Toggle button", button_type="success")
    box.children.append(toggle1)
else:
    toggle.label = 'stop'
    toggle.disabled=False
    if (toggle1 is not None):
        box.children.remove(toggle1)
        toggle1=None

toggle = Toggle(label=“Toggle button”, button_type=“success”)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

So, after all of these approaches have failed, is there any way to create something like a confirm dialog with Bokeh at all ?

Thanks,

Stefan

[1] http://bokeh.pydata.org/en/latest/docs/reference/models/widgets.dialogs.html

[2] http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-widgets


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/2e0aad68-0193-4911-8218-d0bd004b5885%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/fc5a8b04-4325-40a0-afb0-7f860c8c164c%40continuum.io.

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

Hi,

thanks. I extended my code and the confirm dialog is basically working.
The button is inside a layout. When the button is pressed, the layout is extended (using children.append(new_layout)) with two additional buttons and a header (i.e. something like “do you really want to do this ?” and a YES/NO button).
As soon as any of the YES/NO buttons is pressed, the layout is removed again.

While this works, I noticed in my extended code that is breaks the functionality of the plots for some reason.
As soon as I extend the layout with the header and the buttons, the plots no longer work.
When I reload the site, it’s working again.

Any ideas ?

Does extending a layout with additional widget instances somehow break anything ?

Thanks !

···

Am Samstag, 29. Oktober 2016 14:55:05 UTC+2 schrieb Bryan Van de ven:

You need to add “global toggle1” to the top of the callback to use the toggle1 variable in that way.

Thanks,

Bryan

On Oct 29, 2016, at 05:13, [email protected] wrote:

What about approach number (3) ?
Shouldn’t it be possible to just hide/remove a button from an “on_click” callback ?

Thanks,

Stefan

Am Freitag, 28. Oktober 2016 21:51:02 UTC+2 schrieb Bryan Van de ven:

Hi,

The dialog widget has been broken for a long time, and there was no reports or questions about it that entire time, so it was decided to remove it, since there is not really anyone who would be able to work on fixing it any time soon. It will not be present in 0.12.4 or later releases. I’d say the best option for a confirm dialog is to make a bokeh extension that is a thin wrapper around any of the many JS libraries for dialogs. Here are the docs and several full examples for building Bokeh extensions:

    [http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html](http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html)

Thanks,

Bryan

On Oct 28, 2016, at 2:35 PM, Stefan [email protected] wrote:

Hi,

I would like to use a Button widget with a confirm dialog (i.e. “do you really want to do this ? YES/NO”).

Based on the user’s choice in the confirm dialog, I would like to get a callback in the Python code similar to a typical “on_click” event.

So far I have tried and failed with the following approaches:

(1) The Dialog widget [1] appears to do exactly what I want but I can’t get it to work.

I get the JS error “String property ‘content’ given invalid value: Row(7437aac2-…)” with the following code:

#!/usr/bin/env python

import numpy as np

#from bokeh.io import vplot

from bokeh.layouts import column

from bokeh.layouts import row, widgetbox

from bokeh.models import CustomJS, Slider, Paragraph, Dialog, Button

from bokeh.plotting import figure, output_file, show, ColumnDataSource

x = np.linspace(0, 10, 500)

y = np.sin(x)

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)

plot.line(‘x’, ‘y’, source=source, line_width=3, line_alpha=0.6)

descr_box = Paragraph(text=‘content loading…’)

btn_close_loading = Button(label=‘Close Loading’)

dialog_loading = Dialog(

title='loading', content=row(descr_box), name='loading_dialog',
buttons=[btn_close_loading], visible=True)

layout = column(

dialog_loading,
plot,
widgetbox(btn_close_loading),

)

output_file(“slider.html”, title=“slider.py example”)

show(layout)

(2) I tried and failed to use a Javascript callback function that changes a ColumnDataSource object like it is described in the bokeh documentation [2].

Within the JavaScript code I emit a ‘change’ trigger to be able to react on it from within the Python code.

The idea is that while running the bokeh server, I can add an ‘on_change’ callback function to the data source allowing me to get the result of the JavaScript dialog.

While the Javascript Dialog appears as soon as the button is pressed, I never get a callback for the changed ColumnDataSource. In addition, as soon as I add a CustomJS callback

parameter to the Toggle button, the “on_click” callback is no longer working. Neither are any other Python callbacks:

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

x=[0]

y=x

confirmResponse = ColumnDataSource(data=dict(answer=x, y=y))

callback = CustomJS(args=dict(confirmResponse=confirmResponse), code=“”"

        // get data source from Callback args
    var data = confirmResponse.get('data');
    data['answer']
    var confirmResponse = confirm("Really do it?")
    if (confirmResponse) {
            data['answer']=1;
    } else {
            data['answer']=0;
    }
    // trigger update of data source
    confirmResponse.trigger('change');        
""")

def toggle_handler(active):

print("toggle_handler: %s, confirmResponse: %s" % (active,x))

toggle = Toggle(label=“Toggle button”, button_type=“success”, callback=callback)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

confirmResponse.properties()

confirmResponse.on_change(‘data’, default_handler)

confirmResponse.on_change(‘name’, default_handler)

confirmResponse.on_change(‘selected’, default_handler)

confirmResponse.on_change(‘tags’, default_handler)

confirmResponse.on_change(‘change’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

(3) I tried to create my own dialog by just adding a new button from within an “on_click” event. While this works, I can no longer remove that button from the WidgetBox. If I try, I

get the error “UnboundLocalError: local variable ‘toggle1’ referenced before assignment”.

#!/usr/bin/env python

from future import print_function

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.dialogs import Dialog

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox

from bokeh.client import push_session

toggle1=None

def toggle_handler(active):

print("toggle_handler: %s" % (active))
if active:
    toggle.label = 'start'
    toggle.disabled=True
    toggle1 = Toggle(label="Another Toggle button", button_type="success")
    box.children.append(toggle1)
else:
    toggle.label = 'stop'
    toggle.disabled=False
    if (toggle1 is not None):
        box.children.remove(toggle1)
        toggle1=None

toggle = Toggle(label=“Toggle button”, button_type=“success”)

toggle.on_click(toggle_handler)

def default_handler(attrname, old, new):

print ("default handler with attribute %s" %attrname, old, new)

toggle.properties()

toggle.on_change(‘active’, default_handler)

toggle.on_change(‘clicks’, default_handler)

toggle.on_change(‘value’, default_handler)

toggle.on_change(‘disabled’, default_handler)

box = widgetbox(children=[toggle])

document = Document()

document.add_root(box)

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

So, after all of these approaches have failed, is there any way to create something like a confirm dialog with Bokeh at all ?

Thanks,

Stefan

[1] http://bokeh.pydata.org/en/latest/docs/reference/models/widgets.dialogs.html

[2] http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-widgets


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/2e0aad68-0193-4911-8218-d0bd004b5885%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/fc5a8b04-4325-40a0-afb0-7f860c8c164c%40continuum.io.

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

Hi,

here is the code, it might be helpful to others.
For one Test object instance it works fine (i.e. “for i in range(1)” at the bottom of the code), but if you increase it to more instances (e.g. “for i in range(3)”) it only works for the last instance and the first two stop working (including the plots).
I’m not sure what’s going on there. If we manage to fix this issue, the code would be a working confirm dialog :wink:

#!/usr/bin/env python

from future import print_function

import numpy as np

from bokeh.util.browser import view

from bokeh.document import Document

from bokeh.plotting import curdoc

from bokeh.models.widgets import Toggle, Icon, Slider, TextInput

from bokeh.models.widgets import RadioButtonGroup

from bokeh.models.widgets.buttons import Button

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.layouts import widgetbox, layout, column, row

from bokeh.models import Paragraph, Div

from bokeh.plotting import figure

from bokeh.io import curdoc

from bokeh.client import push_session

import inspect

def whoami():

return inspect.stack()[1][3]

def whosdaddy():

return inspect.stack()[2][3]

class Test:

def __init__(self):

    # Slider example

    # Set up data

    self.N = 200

    x = np.linspace(0, 4*np.pi, self.N)

    y = np.sin(x)

    self.source = ColumnDataSource(data=dict(x=x, y=y))

    # Set up plot

    self.plot = figure(plot_height=400, plot_width=400, title="my sine wave",

                  tools="crosshair,pan,reset,save,wheel_zoom",

                  x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])

    self.plot.line('x', 'y', source=self.source, line_width=3, line_alpha=0.6)

    # The button for which we want to have a confirm dialog

    # button_type --> ('default', 'primary', 'success', 'warning', 'danger', 'link')

    self.switch_button = Button(label="Stop thing", button_type="danger")

    self.switch_button.icon = Icon(icon_name='stop')

    self.switch_button.on_click(self.switch_button_clicked)

    self.button_state=True

    self.confirm_layout=None

    self.text = TextInput(title="title", value='my sine wave')

    self.text.on_change('value', self.update_title)

    self.offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)

    self.amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0)

    self.phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)

    self.freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1)

    

    # add callbacks

    for w in [self.offset, self.amplitude, self.phase, self.freq]:

        w.on_change('value', self.update_data)

    # Set up layouts

    inputs = widgetbox(self.text, self.offset, self.amplitude, self.phase, self.freq)

    self.site_layout=layout(

            [

                [inputs, self.plot],

                [self.switch_button],

            ],

            sizing_mode='fixed'

        )

def getLayout(self):

    return self.site_layout

def update_title(self, attrname, old, new):

    self.plot.title.text = self.text.value

def update_data(self, attrname, old, new):

    # Get the current slider values

    a = self.amplitude.value

    b = self.offset.value

    w = self.phase.value

    k = self.freq.value

    # Generate the new curve

    x = np.linspace(0, 4*np.pi, self.N)

    y = a*np.sin(k*x + w) + b

    self.source.data = dict(x=x, y=y)

def confirm_yes_clicked(self):

    print ("%s" % (whoami()))

    if self.button_state:

        self.switch_button.label="Start thing"

        self.switch_button.button_type='success'

        self.switch_button.icon=Icon(icon_name='play')

        self.button_state=False

    else:

        self.switch_button.label="Stop thing"

        self.switch_button.button_type='danger'

        self.switch_button.icon=Icon(icon_name='stop')

        self.button_state=True

    self.switch_button.disabled=False

    self.site_layout.children.remove(self.confirm_layout)

def confirm_no_clicked(self):

    print ("%s" % (whoami()))

    

    self.switch_button.disabled=False

    self.site_layout.children.remove(self.confirm_layout)

def switch_button_clicked(self):

    print ("%s" % (whoami()))

    if (not self.switch_button.disabled):

        self.switch_button.disabled=True

        confirm_paragraph=widgetbox(children=[Paragraph(text="Do you really want to STOP the thing ?")])

        confirm_yes = Button(label="Yes", button_type="success", icon=Icon(icon_name='check'))

        confirm_yes.on_click(self.confirm_yes_clicked)

        confirm_no = Button(label="No", button_type="warning", icon=Icon(icon_name='close'))

        confirm_no.on_click(self.confirm_no_clicked)

        self.confirm_layout =layout(

            [

                [confirm_paragraph], 

                [confirm_yes, confirm_no],

            ],

            sizing_mode='fixed'

        ) 

        self.site_layout.children.append(self.confirm_layout)

document = Document()

for i in range(1):

t=Test()

document.add_root(t.getLayout())

session = push_session(document)

session.show()

if name == “main”:

session.loop_until_closed()

``

···

Am Donnerstag, 10. November 2016 15:14:40 UTC+1 schrieb Stefan Schönleitner:

Hi,

thanks. I extended my code and the confirm dialog is basically working.
The button is inside a layout. When the button is pressed, the layout is extended (using children.append(new_layout)) with two additional buttons and a header (i.e. something like “do you really want to do this ?” and a YES/NO button).
As soon as any of the YES/NO buttons is pressed, the layout is removed again.

While this works, I noticed in my extended code that is breaks the functionality of the plots for some reason.
As soon as I extend the layout with the header and the buttons, the plots no longer work.
When I reload the site, it’s working again.

Any ideas ?

Does extending a layout with additional widget instances somehow break anything ?

Thanks !