Custom ipywidgets - need to call twice to get updated values

Hi all,

I have encountered a problem with ipywidgets that some value has been updated by calling a method, but in the same cell I cannot get the updated value by retrieving the value from the object. Instead, I have to retrieve the value again to get the updated value.

I have created a light example here (I chose to do this way because of the complicated operations and I want to the update step in Python instead of JS):

  • Widget has two values: value1 and value2, and a counter
  • In Front End, I input value1
  • If needed, I want to manually trigger a update step (setting value1 to value2) using counter:
    – counter + 1
    – in JS, if counter changed, set value1 from view to model
    – in Python, if value1 changed, set value2 with new value of value1

However, as shown in the screenshot below, after calling the update method, value1 and value2 are still not changed, but trying to get the two values again gives the updated values:

Screenshot 2021-04-29 at 21.14.39

May I ask what is going on here? In fact, when calling the update method, the values should have been updated, but why in the first time, the values are still shown unchanged? In fact, if I call update method in one cell, and retrieve the values in the next cell, the updated values are shown… This looks weird and I want to understand why and how to overcome the issue, many thanks!

I have attached the code for the very light example here:

from traitlets import Unicode, Int
from ipywidgets import DOMWidget, register

class MyWidget(DOMWidget):
_view_name = Unicode(‘MyWidgetView’).tag(sync=True)
_view_module = Unicode(‘my_widget’).tag(sync=True)

counter = Int(0).tag(sync=True)
value1 = Unicode('default').tag(sync=True)
value2 = Unicode('default').tag(sync=True)

def __init__(self):
    self.observe(self.update, names='value1')

def get_values(self):
    self.counter += 1

def update(self, change):
    self.value2 = change['new']


define(‘my_widget’, ["@jupyter-widgets/base"], function(widgets) {

var MyWidgetView = widgets.DOMWidgetView.extend({
    render: function() {
        this.value1_input = document.createElement('input');
        this.value1_input.type = 'value';
        this.value1_input.value = this.model.get('value1');
        this.model.on('change:counter', this.counter_changed, this);
    counter_changed: function() {
        this.model.set('value1', this.value1_input.value);

return {
    MyWidgetView: MyWidgetView


mw = MyWidget()