Polymer: changing `items` of `dom-repeat` doesn't fully refresh the template

Created on 4 Jun 2015  路  14Comments  路  Source: Polymer/polymer

I have created a custom element and initialize a property inside ready state like this:

Polymer({
 is: 'my-element',
 ready: function() {
  this._isReady = true;
 },
 _customFunc: function() {
  console.log(this._isReady);
 }
});

I am using this _customFunc inside div of my-element, but the problem is this._isReady is always showing undefined in console. How to access it?

pending-response

Most helpful comment

So @zishanj's jsbin above has a hidden dependency. _sampleOutput _says_ it only depends on item:

 <span>{{_sampleOutput(item)}}</span>

But in fact it depends on both item and myItem.length. Since the item doesn't change, the function isn't called again when the array length changes. If you express that dependency:

 <span>{{_sampleOutput(item, myItem.length)}}</span>

It appears that the function is called every time.

http://jsbin.com/jelixuvoji/1/edit

All 14 comments

I couldn't reproduce your problem in this example:
http://jsbin.com/qabede/2/edit

Could you take a look and see how your setup differs?

Note that the ready callback is not available in polymer-micro.html, you'd need to load polymer-mini.html or the full polymer.html library -- that's the only reason I can think of for your element not working...

Thanks for the reply, it works now. Any idea if I am using custom function inside dom-repeat like this:

 <template is="dom-repeat" items="{{myItem}}">
 <span>{{_sampleOutput(item.id)}}</span>
 </template>

In myItem, I have simple array of numbers like this:

this.myItem = [1,2,3,4,5];

If I change this to something like this [1,2,3] then it doesn't call _sampleOutput(item.id), instead it simply updates the output showing result of first three numbers. If I later update it again to [1,2,3,4,5] then it does call _sampleOutput also showing result for all 5 numbers.

What's the issue behind this? Any way to completely refresh the output everytime I update myItem?

I have found a solution to this. I have used indexAs and it has solved the problem.

Did some more test but indexAs has also not solved the issue.

@zishanj: can you check if this JSBin replicate correctly the issue and the array manipulation?

@SmokyBob yes that's the issue... It doesn't call _sampleOutput everytime I click switch button. I have put console.log("here") inside _sampleOutput to demonstrate the issue more correctly. Here is the updated JSBin.

@zishanj IIRC, Objects (Array) don't automatically update when changed; simple data type like bools, strings do though. Objects only propagate their change when replaced.

Perhaps try something like I've done in the following snippet, in particular, building a new object and then this.listItems = data;.

<script>
  Polymer({
    is: 'x-list',
    properties: {
      listItems: {
        type: Array,
        notify: true
      }
    },
    ready: function() {
      var data = [];
      for(var i = 0; i < 15; i++) {
        data.push({
          /* jshint ignore:start */
          name: faker.name.findName(),
          avatar: faker.internet.avatar(),
          strainId: faker.random.uuid()
          /* jshint ignore:end */
        });
      }
      this.listItems = data;
    },
  });
</script>

So @zishanj's jsbin above has a hidden dependency. _sampleOutput _says_ it only depends on item:

 <span>{{_sampleOutput(item)}}</span>

But in fact it depends on both item and myItem.length. Since the item doesn't change, the function isn't called again when the array length changes. If you express that dependency:

 <span>{{_sampleOutput(item, myItem.length)}}</span>

It appears that the function is called every time.

http://jsbin.com/jelixuvoji/1/edit

@arthurevans Thanks a lot, this solves the issue. Otherwise I was thinking the entire day of some method to completely refresh the template.

@arthurevans :+1:
Basically, we need to express as a parameter every dependencies we might have in the function to be sure that it's executed.

Thanks @SmokyBob and @arthurevans , for your time and effort. :+1:

Note that there _is_ a render method on dom-repeat, but you should probably only use it as a last resort. Usually these problems are related to unexpressed dependencies, or imperative changes that don't use this.set.

@arthurevans Ahh ok... Thanks for that info. too but I gave this render also a try but that also doesn't work may be due to unexpressed dependency like you stated.

Oh, of course. render would force the dom-repeat to re-evaluate the filter and sort methods, but the computed binding still thinks nothing's changed.

Was this page helpful?
0 / 5 - 0 ratings