Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aurelia: Binding to computed values

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?

like image 928
doeck Avatar asked Aug 14 '15 12:08

doeck


People also ask

What is reactive binding in Aurelia?

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.

What is bindable Aurelia?

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.


1 Answers

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

like image 168
Jeremy Danyow Avatar answered Oct 23 '22 23:10

Jeremy Danyow