The Code:
App.js
export class App {
constructor() {
this.widgets = [{ name: 'zero'}, {name: 'one'}, {name:'two'}];
this.shipment = { widget: this.widgets[1] };
}
}
App.html
<template>
<require from="./widget-picker"></require>
<require from="./some-other-component"></require>
<widget-picker widget.bind="shipment.widget" widgets.bind="widgets"></widget-picker>
<some-other-component widget.bind="shipment.widget"/>
</template>
widget-picker.js
import {bindable, bindingMode} from 'aurelia-framework';
export class WidgetPicker {
@bindable({ defaultBindingMode: bindingMode.twoWay, changeHandler: 'widgetChanged' })
widget;
@bindable widgets;
widgetChanged(widget) {
// Use an Event Aggregator to send a message to SomeOtherComponent
// to say that they should check their widget binding for updates.
}
}
widget-picker.html
<select value.bind="widget">
<option repeat.for="widget of widgets" model.bind="widget">${widget.name}</option>
</select>
The Problem:
The @bindable
's changeHandler fires the widgetChanged event before the binding gets updated to App.js and its this.shipment.widget
.
So when the Event Aggregator message goes out, the previous value is still set on `this.shipment.widget'.
Question:
Is there a way to make @bindable
's changeHandler wait until all the bindings that will be updated for @bindable are done?
Or is there another callback I can use? Maybe a changedHandler (past tense)?
I did try to add change.delegate="widgetChanged"
to the select
, hoping that the delegate
option would make it slower, but it still fires before the update is fully rolled out.
You could push the work you need to do onto the micro task queue:
import {bindable, bindingMode, inject, TaskQueue} from 'aurelia-framework';
@inject(TaskQueue)
export class WidgetPicker {
@bindable({ defaultBindingMode: bindingMode.twoWay, changeHandler: 'widgetChanged' })
widget;
@bindable widgets;
constructor(taskQueue) {
this.taskQueue = taskQueue;
}
widgetChanged(widget) {
this.taskQueue.queueMicroTask(
() => {
// Use an Event Aggregator to send a message to SomeOtherComponent
// to say that they should check their widget binding for updates.
});
}
}
This will ensure it occurs during the same "turn" of the event loop (as opposed to doing something like setTimeout(...)
).
来源:https://stackoverflow.com/questions/35587033/bindable-changehandler-fires-before-bindings-are-done-updating