polymer: dom-repeat is not properly updating elements on filter/sort

When you utilize the filter/sort attributes the repeated nodes are not updating properly. This is the same behavior that was exhibited in the Polycast on using core-list.

Rob gave a workaround for this by using data-index="{{index}}". This seemed to fix the issue for his use case but when using the filter and sort attributes things get weird really quick.

I threw together a quick demo of this (it utilizes iron-image and iron-ajax so I opted to just give you a repo instead of a jsbin) it is here (Pardon the whimsical API). A link to the running demo: http://jshcrowthe.github.io/dom-repeat-bug/ (After the data loads note the position and color/images utilized then mess with the filters).

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 1
  • Comments: 15 (3 by maintainers)

Commits related to this issue

Most upvoted comments

@jshcrowthe The issue you’re seeing is indeed due to dom-repeat’s reuse of DOM for efficiency.

The pokemon-card locks in state for the element at ready time, rather than when the pokemon property changes: https://github.com/jshcrowthe/dom-repeat-bug/blob/gh-pages/components/pokemon-card/pokemon-card.html#L124

We will likely add an option for dom-repeat to re-create DOM whenever the model would need to change for cases when users can’t avoid using elements whose internal state can’t be dynamically controlled via bindings to its properties, at the cost of less-efficient updates.

However, note that in general we consider it an anti-pattern to create elements that do one-shot state setup, such as inspecting attributes/properties at created or ready time only, as opposed to using observers on those properties, since this is how all native HTML elements behave (consider if you could only set a checkbox’s checked value once at startup…). So I’d encourage you to refactor your pokemon-card element to use observers/computed properties for the properties you use to set the class, such that the state of the element can be controlled dynamically via its API.

Something like…

...
  <div id="wrap" class$="computeClass(pokemon, 'layout horizontal justified center')">
...
    properties: {
      pokemon: Object,
      value: null
    },
    computeClass: function(pokemon, staticClasses) {
      var c;
      if (!pokemon || !Array.isArray(pokemon.types)) {
        c = 'normal-gradient';
      } else {
        c = pokemon.types[0].name + '-gradient';
      }
      return c + ' ' + staticClasses;
    }