Computed property isn't recomputed when array dependency is mutated
Asked Answered
L

1

8

I'm using a computed property as the items for a dom-repeat.

<template is="dom-repeat" items="{{double(values)}}">
  <span>{{item}}</span>
</template>

When its dependency values changes, the property isn't recomputed.

addValue: function() {
  this.push('values', this.values.length+1);
  this.async(this.addValue, 1000);
},

If, instead of mutating values, I set it to a new array, it does work:

this.set('values', this.values.concat(this.values.length+1))

Is this a bug or expected behavior?

Demo: http://plnkr.co/edit/SmAHKMHhSPWgmBhBBzAv?p=preview

Legwork answered 4/6, 2015 at 17:52 Comment(0)
C
11

I spoke with Scott Miles, a member of the team behind Polymer, and I got this back:

In order for the computed property to bind properly, you must use [[double(values.*)]].

The parameter passed to your double function will be an object with properties path, value, and base, just as in path observation.

  • path will refer to a path string that specifies if length or splices was updated in the array,
  • value will be the value of length or splices, and
  • base will refer to your array.

Example:

<template is="dom-repeat" items="[[double(values.*)]]">
  <span>[[item]]</span>
</template>

<script>
  ...
  double: function(e) {
    return e.base.map(function(n) { return n*2; });
  }

Docs: https://www.polymer-project.org/1.0/docs/devguide/properties.html#array-observation

Demo: http://plnkr.co/edit/Idrz5XvLn9SZ35iR8pGT?p=preview

A dom-repeat template expects to be working with a collection, and thus when you bind it to values directly, it knows to keep tabs on the items in values.

Computed properties do not have any such expectations, and so [[double(values)]] doesn't work in this case because it will only update when the values reference itself changes, not when the items in the array change. Using values.* lets Polymer know that it should update the computed property binding when the array's contents are mutated.


I wouldn't post this here in Scott's stead if not for

sjmiles: @vartan: otoh, if you could transcribe what you learned, it would help me, time is my least elastic resource

Calistacalisthenics answered 4/6, 2015 at 18:26 Comment(2)
Also notice that the computed property's function isn't passed the array the directly anymore, but as a property named base. So function(values) {...} becomes function(info) {var values = info.base; ...}Legwork
@TrevorDixon Goodness, I neglected to mention that! Big whoops. I added all the extra detail in :) Thanks for noticing!Calistacalisthenics

© 2022 - 2024 — McMap. All rights reserved.