[IPython-dev] state changes to custom widget trigger update twice

Felix Breuer felix at fbreuer.de
Sun Feb 23 07:10:30 EST 2014


Hello everyone!

Inspired by Jonathan’s D3 demos (https://github.com/jdfreder/ipython-d3), I am trying to wrap my head around creating custom widgets in the IPython notebook. Starting with a minimal (non-D3) example, I have already run into a couple of questions that I couldn’t figure out yet.

Most importantly, it seems like on the JavaScript side update() is always called twice whenever a state change is sent from Python. Why is that and how can I make sure update is called just once?


Concrete example:

from IPython.html import widgets # Widget definitions
from IPython.display import display # Used to display widgets in the notebook
from IPython.utils.traitlets import Unicode, Dict, List # Used to declare attributes of our widget

class MinimalWidget(widgets.DOMWidget):
    _view_name = Unicode('MinimalView', sync=True)
    value = Dict({'hello':'world'},sync=True)

%%javascript

require(["notebook/js/widgets/widget"], function(WidgetManager){
    
    var MinimalView = IPython.DOMWidgetView.extend({
        render: function() { 
            console.log("render");
            this.$container = $('<div></div>').attr('id','container').appendTo(this.$el);
            this.update();
        },
        update: function() {
            console.log("update");
            var dict = this.model.get("value");
            this.$container.empty();
            var that = this;
            $.each(dict, function(key,val) {
                console.log(key,val);
                that.$container.append("<p>" + key + ": " + val + "</p>");
            });
            return MinimalView.__super__.update.apply(this);
        }
    });
    
    WidgetManager.register_widget_view('MinimalView', MinimalView);
});


Now, to try it out:

# show widget
w = MinimalWidget()
display(w)   # update is called once here

# change value
w.value["foo"] = “bar”   # does not trigger update
w.send_state()   # calls update *twice*

w.value = {'one':'two’}   # triggers update *twice*

del w.value["one”]   # does not trigger update
w.send_state()   # calls update *twice*


For applications that use D3, for example, it is important that update is called just once. Calling update twice defeats the purpose of .enter() and .exit(). Any help in figuring out where I went wrong would be greatly appreciated.


Cheers,
Felix


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ipython-dev/attachments/20140223/e42a17e1/attachment.html>


More information about the IPython-dev mailing list