I'm trying to migrate my current Angular.js project to Aurelia.js. I'm trying to do something like that:
report.js
export class Report {
list = [];
//TODO
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="ponent"></require>
<ponent list.bind="list"></ponent>
</template>
So the question is: how to detect when is the list changed?
In Angular.js I can do
$scope.$watchCollection('list', (newVal, oldVal)=>{ my code });
Maybe Aurelia have something similar?
I'm trying to migrate my current Angular.js project to Aurelia.js. I'm trying to do something like that:
report.js
export class Report {
list = [];
//TODO
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="ponent"></require>
<ponent list.bind="list"></ponent>
</template>
So the question is: how to detect when is the list changed?
In Angular.js I can do
$scope.$watchCollection('list', (newVal, oldVal)=>{ my code });
Maybe Aurelia have something similar?
Share Improve this question edited Nov 18, 2015 at 20:24 Jeremy Danyow 26.4k12 gold badges90 silver badges135 bronze badges asked Nov 18, 2015 at 18:04 Egor MalkevichEgor Malkevich 1,5361 gold badge11 silver badges26 bronze badges3 Answers
Reset to default 9For @bindable
fields the listChanged(newValue, oldValue)
would be called whenever the list
value is updated. Please take a look Aurelia docs
@customAttribute('if')
@templateController
export class If {
constructor(viewFactory, viewSlot){
//
}
valueChanged(newValue, oldValue){
//
}
}
You can also use ObserveLocator
as described in Aurelia author's blogpost here:
import {ObserverLocator} from 'aurelia-binding'; // or 'aurelia-framework'
@inject(ObserverLocator)
class Foo {
constructor(observerLocator) {
// the property we'll observe:
this.bar = 'baz';
// subscribe to the "bar" property's changes:
var subscription = this.observerLocator
.getObserver(this, 'bar')
.subscribe(this.onChange);
}
onChange(newValue, oldValue) {
alert(`bar changed from ${oldValue} to ${newValue}`);
}
}
UPD
As mentioned in this question by Jeremy Danyow:
The ObserverLocator is Aurelia's internal "bare metal" API. There's now a public API for the binding engine that could be used:
import {BindingEngine} from 'aurelia-binding'; // or from 'aurelia-framework'
@inject(BindingEngine)
export class ViewModel {
constructor(bindingEngine) {
this.obj = { foo: 'bar' };
// subscribe
let subscription = bindingEngine.propertyObserver(this.obj, 'foo')
.subscribe((newValue, oldValue) => console.log(newValue));
// unsubscribe
subscription.dispose();
}
}
Best regards, Alexander
Your original code will work with one small tweak:
report.js
import {bindable} from 'aurelia-framework'; // or 'aurelia-binding'
export class Report {
@bindable list; // decorate the list property with "bindable"
// Aurelia will call this automatically
listChanged(newList, oldList){
enter code here
}
}
report.html
<template>
<require from="ponent"></require>
<ponent list.bind="list"></ponent>
</template>
Aurelia has a convention that will look for a [propertyName]Changed
method on your viewmodel and call it automatically. This convention is used with all properties decorated with @bindable
. More info here
It seems better solution for current case is CustomeEvent
So plete solution would look like that
report.html
<template>
<require from="ponent"></require>
<ponent list.bind="list" change.trigger="listChanged($event)"></ponent>
</template>
ponent.js
@inject(Element)
export class ComponentCustomElement {
@bindable list = [];
//TODO invoke when you change the list
listArrayChanged() {
let e = new CustomEvent('change', {
detail: this.lis
});
this.element.dispatchEvent(e);
}
}
You have to change ponent element, add some trigger function that sand you change event. I suppose that ponent knows when list changed.