alesc
alesc

Reputation: 2780

Polymer 1.0: Best practice for managing a simple list of items

I have created a simple prototype for displaying and editing a list of people. The prototype can be found here: JSBin.

As you can see, when "Save" is pressed, the item is written back to the array using the array mutation API. I am not sure whether this is actually needed, since objects are always assigned by reference.

However, the "Save" button does not update the item in the list. But when you edit it again, the newly changed value is somehow preserved in the form. I guess the change does happen in-memory, but the dom-repeat does not trigger a new rendering of the list.

I have also set the observe property on the dom-repeat, but it does not seem to make any difference.

My question is twofold:

  1. What needs to be changed so that the list will be updated upon saving the item.
  2. Is there a better way (common best practice) for managing lists of items (with the usage of two-way data-binding).

Upvotes: 4

Views: 147

Answers (1)

Dogs
Dogs

Reputation: 3187

Short answer: Switch your save function to this

app.save = function(e) {
   app.splice('people', app.selectedIndex, 1, {name: app.selected.name, surname: app.selected.surname});
   app.selectedIndex = -1;
};

Long answer:

The reason you need to do this is slightly complicated, but it has to do with performance optimizations inside of dom-repeat. When dom-repeat's array gets updated, it doesn't simply delete all of its child nodes and re-render everything, because that could be expensive. Instead, it loops through all of the template instances it currently has as children, and checks to see if their item model has changed. For each template, it does a reference equality check to see if they are the same object or not. If they are they same, it does nothing. If they aren't, it re-renders that template.

In your case, you're splicing the array with the same object that is already there. So when the dom-repeat does this optimization check, it sees that the item is the same object as before, and does nothing. If you create a new object, however, this check will fail and it will re-render the template instance...thus, it works.

Now, why doesn't it just update when the object gets mutated? The answer to that has to due with the fact that Polymer's data checking is based on 'path notification', rather than something expensive like dirty checking. When a property gets updated, Polymer fires an event to every child node that is data-bound to that property. The problem is, your forms are not data-bound to the property as an element in the 'people' array. They're bound to a different property, 'selected'. And even though these are backed by the same object, the property names are different, so the notification paths do not match up; app.selected.name is the path that gets notified when you change John Doe's first name, not app.people.0.name, which is the path the dom-repeat is looking for change notifications along.

As for the second part of your question, I would recommend that you avoid two-way data-binding whenever possible. It doesn't rely on dirty-checking like Angular does, so it's not as huge of a performance problem, but it still does have a lot of overhead.

Upvotes: 2

Related Questions