Reputation: 1339
I have a property on my class:
class Control {
@bindable households;
get people() {
return households
.map(household => househould.people)
.reduce((g1, g2) => g1.concat(g2), []);
}
}
Which I use to compute a collection of all people[]
within all households which is then rendered here:
<ul>
<li repeat.for="person of people">
${person.firstName} ${person.lastName} - ${person.phone}
</li>
</ul>
I need the list to update whenever people are added to a household, OR if any of the rendered properties, firstName
, lastName
, phone
, for any element in the computed collection is updated. How can I do this in Aurelia? If I use @computedFrom()
it will not detect changes to elements of the array, and since the list of people in all households is dynamic, I cannot just create an observer for each element without creating a system for managing when observers should be subscribed / unsubscribed.
Upvotes: 0
Views: 628
Reputation: 307
You must avoid dirty-checking
as far as possible, signals are the perfect option for your scenario. Just bear in mind that if you want to use computedFrom
on an array you can do so by watching its length
property for instance rather than dirtyChecking
, sth like the following @computedFrom("myArray.length")
Upvotes: 0
Reputation: 12295
Leave off @computedFrom()
and you'll achieve the desired behavior.
export class App {
@bindable households;
get people() {
const households = this.households || []; // Make sure househoulds is defined.
return households.reduce((people, household) => people.concat(household.people), []);
}
}
https://gist.run/?id=040775f06aba5e955afd362ee60863aa
Upvotes: 2
Reputation: 1339
Right as I was about to give up on being able to Google for a solution, Aurelia Signaling came to the rescue. This code ended up working for me:
<ul>
<li repeat.for="person of people">
<!-- May work without this rendering method,
this is just closer to what my actual code is doing. -->
${renderPersonInfo(person) & signal: 'example-signal'}
</li>
</ul>
And the class:
import {BindingSignaler} from 'aurelia-templating-resources';
@inject(BindingSignaler)
class Control {
@bindable households;
constructor(bindingSignaler) {
this.bindingSignaler = bindingSignaler;
//Obviously, you can have this trigger off any event
setInterval(() => this.bindingSignaler.signal('example-signal'), 1000);
}
get people() {
return households
.map(household => househould.people)
.reduce((g1, g2) => g1.concat(g2), []);
}
}
Upvotes: 1