ipywidgets
ipywidgets copied to clipboard
Custom ipywidgets - need to call twice or in new cell 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 in the same cell. Instead, I have to retrieve the value again to get the updated value or in another cell. This is not a big issue in Notebook, but the above step is actually another method in my problem and I need to retrieve the updated value in script for use with another process which will be presented in the notebook. So I do need to get the updated value as an intermediate step.
I have created a light example here - I chose to update the value2 this way in Python because of the complicated operations and data duplication so I want 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:

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, thanks!
`from traitlets import Unicode, Int from ipywidgets import DOMWidget, register
@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):
super().__init__()
self.observe(self.update, names='value1')
def get_values(self):
self.counter += 1
def update(self, change):
self.value2 = change['new']
%%javascript require.undef('my_widget');
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.el.appendChild(this.value1_input);
this.model.on('change:counter', this.counter_changed, this);
},
counter_changed: function() {
this.model.set('value1', this.value1_input.value);
this.touch();
}
});
return {
MyWidgetView: MyWidgetView
};
});
mw = MyWidget() mw `
I have the same issue.
Things I tried
I thought maybe the JS side does not have the time to update if it's in the same cell but
import time
mw.get_values()
time.sleep(10)
print(mw.value1, mw.value2)
did not work.
Then I added a console.log on the JS side of get_values and executing the following cell
mw.get_values()
assert False
never entered in get_values
So I made get_values an async function, the snippet now looks like this:
await mw.get_values()
print(mw.value1, mw.value2)
Now we do enter in get_values but the old ones are still printed It still does not solves the issue.
Does someone have an idea? Or any place I could look for an implementation? I'm kinda lost here