Is there a way for Aurelia Binding of method to watch Array for adding/removing elements or elements change?
For example
<div>${methodName(propertyArray)}</div>
I would probably define a property (say myMethodNameResult
) in my view model, then use CollectionObserver from BindingEngine to subscribe to changes to the propertyArray and update my property inside the subscription handler.
See https://aurelia.io/docs/binding/observable-properties#observing-collections
That is one possible solution however I have very deep collection. 3 level nested. I have array of items inside array of subitems inside array of subsubitems. I need to display count number of subsubitems that have checked property true.
Every time subsubitem change count should be updated but it is not. Your solution is slow. I need to foreach 3 times to check what happens. Is there any cleaner solution?
I’m not sure why you need to foreach 3 times when an observer updates, you should only have to do that initially to observe every array. The subscription gives you the previous value so you can just subtract the previous from the count and add the new value.
let total = 0;
let subscription = bindingEngine.collectionObserver(this.myCollection)
.subscribe((newValue, oldValue) => {
if (oldValue)
total -= oldValue;
if (newValue)
total += newValue;
});
If you don’t want to mess with observables then the fastest way is to make that event happen yourself whenever any individual value is updated.
Edit ahh he only had the collection observer
Use the propertyObserver
let array = [];
let subscriptions = array.map(
item => bindingEngine
.propertyObserver(item, 'count')
.subscribe((newValue, oldValue) => { ... })
);
You can probably reach the recursive levels with array.reduce()
You can then use the collectionObservers if you have to watch for array changes to unbind the old rebind the new sub array
I found clean way to solve this. I just created new user control that have @bindable item. Then inside this user control I created property that return count value of item.checked. This way I don’t need method that accepts array but I have property instead. This user control is update UI and count every time it changes automatically so I don’t need to iterate trough items etc…
Cool!
I’ve been struggling to find a clean and general solution for this pattern. Signals are inadequate because they don’t work for view-model computed properties, and view bindings can only bind to a single signal.
Using collectionObserver
is awkward, not giving a direct way for bound elements to refresh simply on collection size changes. (BTW I think the code example given for collectionObserver
above is incorrect in the subscribe
function - the function params are not the count).
Thanks for posting your elegant solution!
Gotta say though in the end I could figure out what you’re doing in your solution that causes a method in a binding to be reinvoked when the size of a collection changes. I ended up using signals. My use-case may be different from yours.