<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hello everyone!<div><br></div><div>Inspired by Jonathan’s D3 demos (<a href="https://github.com/jdfreder/ipython-d3">https://github.com/jdfreder/ipython-d3</a>), 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.</div><div><br></div><div>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?</div><div><br></div><div><br></div><div>Concrete example:</div><div><br></div><div><div>from IPython.html import widgets # Widget definitions</div><div>from IPython.display import display # Used to display widgets in the notebook</div><div>from IPython.utils.traitlets import Unicode, Dict, List # Used to declare attributes of our widget</div></div><div><br></div><div><div>class MinimalWidget(widgets.DOMWidget):</div><div> _view_name = Unicode('MinimalView', sync=True)</div><div> value = Dict({'hello':'world'},sync=True)</div></div><div><br></div><div><div>%%javascript</div><div><br></div><div>require(["notebook/js/widgets/widget"], function(WidgetManager){</div><div> </div><div> var MinimalView = IPython.DOMWidgetView.extend({</div><div> render: function() { </div><div> console.log("render");</div><div> this.$container = $('<div></div>').attr('id','container').appendTo(this.$el);</div><div> this.update();</div><div> },</div><div> update: function() {</div><div> console.log("update");</div><div> var dict = this.model.get("value");</div><div> this.$container.empty();</div><div> var that = this;</div><div> $.each(dict, function(key,val) {</div><div> console.log(key,val);</div><div> that.$container.append("<p>" + key + ": " + val + "</p>");</div><div> });</div><div> return MinimalView.__super__.update.apply(this);</div><div> }</div><div> });</div><div> </div><div> WidgetManager.register_widget_view('MinimalView', MinimalView);</div><div>});</div></div><div><br></div><div><br></div><div>Now, to try it out:</div><div><br></div><div># show widget</div><div><div>w = MinimalWidget()</div><div>display(w) # update is called once here</div></div><div><br></div><div># change value</div><div>w.value["foo"] = “bar” # does not trigger update</div><div>w.send_state() # calls update *twice*</div><div><br></div><div>w.value = {'one':'two’} # triggers update *twice*</div><div><br></div><div>del w.value["one”] # does not trigger update</div><div><div>w.send_state() # calls update *twice*</div></div><div><br></div><div><br></div><div>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.</div><div><br></div><div><br></div><div>Cheers,</div><div>Felix</div><div><br></div><div><br></div></body></html>