-
-
Save pbugnion/63cf43b41ec0eed2d0b7e7426d1c67d2 to your computer and use it in GitHub Desktop.
I tried this same fix after discovering the unpack_models function yesterday, but it was broken because I was missing the first empty Object argument to widgets.DOMWidgetModel.extend(). Why is that argument needed? What is it doing?
The first argument extends the class prototype, the second argument extends static properties of the class. For instance, in ipyleaflet:
var LeafletLayerModel = widgets.WidgetModel.extend({
defaults: _.extend({}, widgets.WidgetModel.prototype.defaults, {
_view_name: 'LeafletLayerView',
_model_name: 'LeafletLayerModel',
_view_module: 'jupyter-leaflet',
_model_module: 'jupyter-leaflet',
opacity: 1.0,
bottom: false,
options: [],
name: '',
base: false,
popup: null,
popup_min_width: 50,
popup_max_width: 300,
popup_max_height: null,
})
}, {
serializers: _.extend({
popup: { deserialize: widgets.unpack_models }
}, widgets.WidgetModel.serializers)
});
... instances of LeafletLayerModel
will have the defaults()
method as specified here. The class LeafletLayerModel
will have the serializers
static attribute.
The way this would be translated into 'modern' Javascript is:
class LeafletLayerModel extends widgets.WidgetModel {
defaults() {
return {
...super.defaults(),
_view_name: 'LeafletLayerView',
_model_name: 'LeafletLayerModel',
/* other attributes omitted for brevity */
}
}
static serializers = {
...widgets.DOMWidgetModel.serializers,
popup: {deserialize: widgets.unpack_models},
}
}
The peculiar syntax with the two arguments to widgets.DOMWidgetModel.extend
is a quirk of Backbone classes. See the API reference: Backbone.Model.extend(properties, [classProperties])
.
Since Test is a DOMWidget, shouldn't it be widgets.DOMWidgetModel.serializers and not widgets.WidgetModel.serializers? Or does that make no difference?
Yes, it definitely should -- I'll update the notebook.
According to the source, by inheriting from the wrong class, I'm stopping the user from passing a layout
and style
traitlet from the kernel.
Additionally: do you know if this part of the ipywidgets API documented anywhere other than in the code? Seems like it should be added to the low level widget tutorial... a search for unpack_models turns up no hits, currently.
Yes, it definitely should! The interface for creating custom widgets is very under-documented. If I have time, I'd love to work on that eventually.
Excellent, very clear-- thank you. Will that "modern" version run in most browsers?
I'm a very skilled Python guy, but I have written very little javascript, and what little I know is mostly the old syntax, I have never written, for example, typescript or used the newer ECMA 5, 6, 7, 8, 9 stuff (I assume that is what you have written there?).
I might try submitting a pull request to update the docs with this small tidbit. If I can feel confident enough I know what I am doing now (I believe I do).
Will that "modern" version run in most browsers?
No -- to get sufficient browser support, it needs to be transpiled to 'old' [*] JavaScript using a tool like Babel or typescript, and bundled using something like webpack.
A good heuristic is:
- if you have a very simple frontend, then keeping it in 'old' JS is probably safest. If you have no experience of Babel and webpack, I'd expect it to take you a day or two just to get something working (based on my personal experience as a Python developer who had to learn JS that way).
- if you are going to develop a rich frontend library, then the investment is worth it. 'New' transpiled JS is just nicer to write.
[*] here, 'old' JavaScript means JavaScript that can be executed by all the browsers you want to support. It's useful to note that this isn't well-defined: the latest version of Chrome will accept lots of modern syntax, while IE 11 won't. For instance, pasting the following in my chrome console works just fine:
class Hello {
static prop = {
a: 22
}
}
Hello.prop
# {a: 22}
I might try submitting a pull request to update the docs with this small tidbit
Yes! That would be great! Jupyter widgets are purely maintained by the community -- there is no commercial company behind them, so we're very heavily reliant on contributions like these.
Thanks so much for this- it has been driving me crazy for days. A few questions:
I tried this same fix after discovering the
unpack_models
function yesterday, but it was broken because I was missing the first empty Object argument to widgets.DOMWidgetModel.extend(). Why is that argument needed? What is it doing?Since
Test
is aDOMWidget
, shouldn't it bewidgets.DOMWidgetModel.serializers
and notwidgets.WidgetModel.serializers
? Or does that make no difference?Additionally: do you know if this part of the ipywidgets API documented anywhere other than in the code? Seems like it should be added to the low level widget tutorial... a search for
unpack_models
turns up no hits, currently.