Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Uncaught (in promise) TypeError: Cannot read property 'connect' of undefined #10345

Open
Singletoned opened this issue Jul 27, 2020 · 6 comments
Milestone

Comments

@Singletoned
Copy link

This appears to be related to #9218

When I add a dropdown with a callback to a Bokeh chart, then in the browser it causes a Javascript error.

I'm very new to Bokeh, so it is quite possible that I am doing something wrong, though I suspect that this isn't the intended behaviour anyway. I'd be glad to hear of any workarounds I can do.

I'm trying to add a dropdown that allows users to choose which groups of data will be shown in the chart (roughly similar to the way you can click on the legend to show hide things).

ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)

bokeh==2.1.1
Ubuntu and OSX
Python 3.8
Latest Chrome and Chrome Canary, latest Firefox (slightly different error in Firefox Uncaught (in promise) TypeError: n is undefined)

Description of expected behavior and the observed behavior

I expect to see the chart on the page. I don't see the chart on the page.

If I add a callback to the dropdown, it breaks. If I don't add the callback, it works.

Complete, minimal, self-contained example code that reproduces the issue

from bokeh.io import show
from bokeh.models import Dropdown, ColumnDataSource, CustomJS
from bokeh.plotting import figure
from bokeh.layouts import column, row

p = figure()
source_line = ColumnDataSource(dict(x = [1, 2], y = [2, 1]))
source_circle = ColumnDataSource(dict(x = [1, 2], y = [2, 1]))
line = p.line('x', 'y', source = source_line)
circle = p.circle('x', 'y', source = source_circle)

dropdown = Dropdown(label="Lines or Circles", button_type="warning", menu=['Lines', 'Circles'])

callback = CustomJS(code='console.log("Callback!")')
dropdown.js_on_change('value', callback)

layout = row(
    column(dropdown),
    column(p)
)

show(layout)

Stack traceback and/or browser JavaScript console output

From Chrome

bokeh-2.1.1.min.js:176 Uncaught (in promise) TypeError: Cannot read property 'connect' of undefined
    at m.connect (bokeh-2.1.1.min.js:176)
    at m._update_property_callbacks (bokeh-2.1.1.min.js:239)
    at m.connect_signals (bokeh-2.1.1.min.js:239)
    at Function._initialize_references_json (bokeh-2.1.1.min.js:162)
    at Function.from_json (bokeh-2.1.1.min.js:162)
    at g (bokeh-2.1.1.min.js:160)
    at bokeh-2.1.1.min.js:160
    at bokeh-2.1.1.min.js:180

From Firefox

Uncaught (in promise) TypeError: n is undefined
    connect https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:176
    _update_property_callbacks https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:239
    connect_signals https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:239
    _initialize_references_json https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:162
    from_json https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:162
    g https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:160
    embed_items https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:160
    defer https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js:180
@mattpap
Copy link
Contributor

mattpap commented Jul 27, 2020

Dropdown widget is a button-like widget and so it doesn't have value property. js_on_change() doesn't do proper sanity checking, so it happily registers a callback that can't work. Use this instead:

callback = CustomJS(code='console.log("Callback!", cb_obj)')
dropdown.js_on_event('menu_item_click', callback)

where cb_obj is an instance of MenuItemClick event, which you can use to determine which menu item was clicked.

@mattpap mattpap added type: bug and removed TRIAGE labels Jul 27, 2020
@mattpap mattpap added this to the next milestone Jul 27, 2020
@mattpap
Copy link
Contributor

mattpap commented Jul 27, 2020

I will consider this to be a bug, because a simple usage mistake should not result in a JS exception.

@Singletoned
Copy link
Author

Thanks for the fast response!

Where can I find (or work) out which widgets support which events? (I searched the docs for js_on_event and couldn't find what I was looking for)

@Singletoned
Copy link
Author

If you have that defined somewhere, I could possibly add sanity checking to js_on_event myself (I'm a Python developer).

@bryevdv
Copy link
Member

bryevdv commented Jul 27, 2020

@mattpap I have now run in to this exact question on Discourse, SO, and other places at least a dozen times. I have to say I think changing this in this way was a mistake, and I wish that I had better noticed the original work so that it could have been more thoroughly discussed. Other frameworks (e.g. Dash) certainly treat the combo box callback as a function that receives the bare value that can then be used immediately. It's certainly far simpler for users, and a reasonable expectation that the API be centered around the value since that is the thing that is actually of interest. I would in fact, suggest adding a value property back that gets set whenever the event is emitted.

@Singletoned Thank you for the offer, unfortunately the information is defined in BokehJS, on the JavaScript side. It would certainly good to have a Python side specification for things that emit events, but that would be a bit of a project (e.g. there would need tests to make sure JS/Python are always in agreement, and a main point of that information would be to automate docs generation, so some docs work as well). That said, certainly happy to advise further if there's still interest.

@mattpap
Copy link
Contributor

mattpap commented Jul 27, 2020

We have Select widget which offers the "combo-box" look&feel and supports value property. Dropdown is supposed to allow users to take action instead of maintaining a value. However, bokeh's APIs make the semantic difference between such widgets fade (e.g. Button.clicks allows users to use value APIs where action APIs are more appropriate). I think it's a matter for insufficient documentation that would point users in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants