Does this.model.set('value', ...) trigger 'change:value' event?

I have been playing with ipywidget for only a week so please be gentle :slight_smile:
I am currently trying to build a custom widget for audio annotation.

On Javascript side, I have something like


render() {
   ...
   this.model.on('change:regions', this.regions_changed, this);
   ...
}

regions_changed() {
   console.log("regions_changed");
}

sync_regions(regions) {
    this.model.set('regions', regions);
    this.touch();
    // this.model.save_changes();  
}

On Python side, I have something like

@widgets.register
class AudioWidget(widgets.DOMWidget):
    ...
    regions = List().tag(sync=True)

As expected, calling sync_regions(regions) on Javascript side will result in regions attribute be updated on Python side.

However, the change:regions event is also triggered on Javascript side. Is this expected?

My expectations were that it should only be triggered when regions is updated manually on Python side (and not through the built-in ipywidget Javascript → Python sync).

If it is the expected behavior, how would one go to prevent the change:regions event from being triggered?

Thanks for your help!

PS: same behavior happens using this.model.save_changes() instead of this.touch() but I probably don’t know what I am doing here :slight_smile:

Is this expected?

Yes. For example, if you have multiple copies of your widget on the page, they’ll have different View objects, and you may wish them to change based on something happening in another copy, irrespective of the server.

prevent the change:regions event from being triggered?

I don’t think you can, but you could ignore it in a specific View by having something like:

if(!this._i_changed_the_regions) {
  console.log("regions_changed");
}
...
this._i_changed_the_regions = true;
this.model.set('regions', regions);
this.touch();
this._i_changed_the_regions = false;

this would allow other Views to sync to the same content. If you really didn’t want it to keep multiple copies in sync, you could set _i_changed_the_regions on this.model itself, and then no copies would update.

Thanks for the quick (and useful!) answer @bollwyvl.

This behavior totally makes sense for multiple views.
Will go ahead and use the i_changed_this trick.

Thanks a lot.