In my application I need to have some forms with rows of values that have to be summed. I need to loop through these rows, having inputs for them and then building a sum that should be updated when the inputs are edited.
Here is a simplified example: The class:
export class example {
items = [
{ id: 1, val: 100 },
{ id: 2, val: 200 },
{ id: 3, val: 400 }
];
get sum() {
let sum = 0;
for (let item of this.items) {
sum = sum + parseFloat(item.val);
}
return sum;
}
}
The view:
<div repeat.for="item of items" class="form-group">
<label>Item ${$index}</label>
<input type="text" value.bind="item.val" class="form-control" style="width: 250px;">
</div>
<div class="form-group">
<label>Summe</label>
<input type="text" disabled value.one-way="sum" class="form-control" style="width: 250px;" />
</div>
Until here everything is working like I expect it to do. But: it's dirty checking on sum
all the time and I fear running into performance issues in the more complicated app. So I tried to use the @computedFrom
decorator, but none of these versions works:
@computedFrom('items')
@computedFrom('items[0]', 'items[1]', 'items[3]')
@computedFrom('items[0].val', 'items[1].val', 'items[3].val')
In all of these cases, the sum is just calculated once but not after editing the values. And the last 2 would be no good solution, because I can have a changing amount of items in my model.
Any suggestions how I could get a computed value that is changed when fields which it depends on are changed without having the dirty checking?
Reactive Binding By using adaptive techniques Aurelia selects the most efficient way to observe each property in your model and automatically syncs your UI and your state with best-in-class performance.
Aurelia supports binding HTML and SVG attributes to JavaScript expressions. Attribute binding declarations have three parts and take the form attribute. command="expression" . attribute : an HTML or SVG attribute name.
use @computedFrom
on the item val
prop:
import {computedFrom} from 'aurelia-framework';
export class Item {
constructor(id, val, parent) {
this.id = id;
this._val = val;
this.parent = parent;
}
@computedFrom('_val')
get val() {
return this._val;
}
set val(newValue) {
this._val = newValue;
this.parent.calculateSum();
}
}
export class Example {
sum = 0;
items = [
new Item(1, 100, this),
new Item(2, 200, this),
new Item(3, 400, this)
];
constructor() {
this.calculateSum();
}
calculateSum() {
let sum = 0;
for (let item of this.items) {
sum = sum + parseFloat(item.val);
}
this.sum = sum;
}
}
For some other ideas, take a look at https://stackoverflow.com/a/32019971/725866
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With