Summary
See the toy example Azure notebook hosted at this link. The notebook can be cloned or downloaded from there, but all of the code is also below for convenience.
When all the cells are run, the javascript console reports these errors (abbreviated) in the final cell:
Error: Could not create a view for model id 91700d0eb745433eaee98bca2d9f3fc8
at promiseRejection (utils.js:119)
Error: Could not create view
at promiseRejection (utils.js:119)
Uncaught (in promise) TypeError: Cannot read property 'then' of undefined
Uncaught (in promise) TypeError: Cannot read property 'then' of undefined
Not sure where I am going wrong.
Details
The notebook contains python and javascript code, and utilizes the ipywidgets library, which relies heavily on Backbone. The back end code (python, cell #1) creates a ipywidgets.DOMWidget subclass widget, Test (a Backbone model mirrored in the front end). The front end code (javascript, cell #2) creates a ipywidgets.DOMWidgetView subclass, TestView, which is instantiated by the widget when it is rendered to the page.
The Test model widget has a children member made up of multiple "sub-widgets" (which are also models). These widgets are instances of the python class Sub. When a view of Test is rendered, I want to instantiate and render the views of the children widgets and attach them to the view of the parent Test widget (note: that final part hasn't been implemented yet below).
The problem is that when I try to follow the ipywidgets API to create children views, populating the ViewList array by instantiating the children views using the create_child_view method on each child model is not working.
The API for this kind of thing isn't particularly well documented, so I'm doing my best to follow various similar examples of how to instantiate sub-views using child models from within a parent view, such as the parent widgets in ipywidgets itself and in ipyleaflet. But nothing I do seems to get the creation of children views working.
Code
Cell 1 (server side jupyter python kernel)
import ipywidgets.widgets as widgets
from traitlets import Unicode, List, Instance
from IPython.display import display
class Sub(widgets.DOMWidget):
"""Widget intended to be part of the view of another widget."""
_view_name = Unicode('SubView').tag(sync=True)
_view_module = Unicode('test').tag(sync=True)
_view_module_version = Unicode('0.1.0').tag(sync=True)
class Test(widgets.DOMWidget):
"""A parent widget intended to be made up of child widgets."""
_view_name = Unicode('TestView').tag(sync=True)
_view_module = Unicode('test').tag(sync=True)
_view_module_version = Unicode('0.1.0').tag(sync=True)
children = List(Instance(widgets.Widget)).tag(sync=True,
**widgets.widget_serialization)
def __init__(self, subs):
super().__init__()
self.children = list(subs)
Cell 2 (front end jupyter notebook code)
%%javascript
require.undef('test');
define('test', ["@jupyter-widgets/base"], function(widgets) {
var SubView = widgets.DOMWidgetView.extend({
initialize: function() {
console.log('init SubView');
SubView.__super__.initialize.apply(this, arguments);
},
render: function() {
this.el.textContent = "subview rendering";
},
});
var TestView = widgets.DOMWidgetView.extend({
initialize: function() {
console.log('init TestView');
TestView.__super__.initialize.apply(this, arguments);
this.views = new widgets.ViewList(this.add_view, null, this);
this.listenTo(this.model, 'change:children', function(model, value) {
this.views.update(value);
}, this);
console.log('init TestView complete');
},
add_view: function (child_model) {
return this.create_child_view(child_model);
},
render: function() {
this.views.update(this.model.get('children'));
this.el.textContent = 'rendered test_view';
},
});
return {
SubView : SubView,
TestView : TestView,
};
});
Cell 3 (python code for testing)
models=[Sub() for _ in range(4)]
for m in models:
display(m)
t=Test(models)
t # javascript console errors occur here, after attempting to view parent
More specific information about the actual project I am working on is at this github issue if anyone is interested.
from Child widget creation in ipywidgets produces an error using ViewList and create_child_view
No comments:
Post a Comment