Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iron list does not re-render a mutated item #504

Open
Flamenco opened this issue Dec 22, 2017 · 13 comments
Open

Iron list does not re-render a mutated item #504

Flamenco opened this issue Dec 22, 2017 · 13 comments

Comments

@Flamenco
Copy link
Contributor

Flamenco commented Dec 22, 2017

Description

If I change a field in a object of my list, the iron list does not update my template. The only way I can get it to update is by calling Object.assign({}, myObject) and then either splicing or setting the cloned item via the array manipulation API.

I can set mutableData = true on my the iron-list, and get everything working, but I would like to see the data manipulation work when that is not set however.

This works:

const clone = Object.assign({}, myObject);
clone.foo = 'new value';
this.set(`filteredItems.5`, clone);

I am aware of the mutability issues with the framework but I think this should be enough to trigger a refresh:

element.set('theList.5.foo', bar)

One issue I see is that _itemsChanged: function(change) does not receive the full path to the mutation, only the list. That makes it difficult to detect that an item was modified but still the same object...

Furthermore, the old item is sometimes cached so if I clear the list, then reload it, iron-list still uses the old value, even if I make a new copy of the list.

theList = []; 
theList = oldList.slice()

At the very least, iron-list should allow me to manually invalidate/flush/refresh an object in the list by index or object. IMO both the Polymer array mutation and iron-list API should provide means to indicate an object has changed.

For the record, these also do not work

this.notifyPath('theList');
this.notifyPath('theList.5');
this.notifyPath('theList.5.foo');
this.splice('theList', 5, 1,  theOriginalItemUpdated)
@Flamenco Flamenco changed the title Iron list does not re-render an item in array unless Iron list does not re-render a mutated item Dec 22, 2017
@hendrikebbers
Copy link

+1 any update here?

@Martin-Palringo
Copy link

Martin-Palringo commented Feb 26, 2018

This seems to have broken in 2.x, in 1.x it worked fine.

Not responding to data updates seems like a fundamental problem for many applications. Is this being investigated?

Note the .set('items.5', itemClone) workaround doesn't seem to work for me too.

@keanulee
Copy link
Contributor

Does calling the private method list._render() fix it? If so the issue might be with detecting when to call it on items.splices change (https://github.com/PolymerElements/iron-list/blob/master/iron-list.html#L1100).

Another way to workaround these mutability issues is to use immutable objects/arrays. That is, construct new objects/arrays when items changes (this is what Redux and other state management libraries typically do).

@Flamenco
Copy link
Contributor Author

Another way to workaround these mutability issues is to use immutable objects/arrays. That is, construct new objects/arrays when items changes (this is what Redux and other state management libraries typically do).
@keanulee

This does not work in Polymer iron list as it should. Please look at the first comment. There is a severe caching problem.

theList = []; 
theList = oldList.slice()

@keanulee
Copy link
Contributor

I meant immutability at all levels - this means a deep copy of the oldList array (e.g. a new object for every changed index).

list = [
  ...oldList.slice(0, i),
  {
    ...oldObjAtI,
    changedProp
  },
  ...oldList.slice(i+1)
];

This is because equality operators are still used within iron-list for each item to determine when to re-render.

@Flamenco
Copy link
Contributor Author

I have used react before, and adapted to the mutability issues; This component takes it to a whole new level though.

Does calling the private method list._render() fix...

As mentioned in the first post, an invalidate method should be part of the public API.

When it works, it works GREAT though ;)

@NicolasRannou
Copy link

@Flamenco did you figure it out?

A demo/example would be great - I tried the fixed suggested above and nothing seems to work.

@NicolasRannou
Copy link

NicolasRannou commented Mar 16, 2018

<iron-list id="list" items="[]" as="feed" scroll-target="[[scrollTarget]]">
      <template>
        <div class="feed" on-click="_openFeed">
          <div tabindex$="[[tabIndex]]">
            <div class="pad">
              <div class$="[[feed.class]]">
                   [[feed.class]]
              </div>
            </div>
          </div>
        </div>
      </template>
    </iron-list>

and trying to update class in the on-click callback:

     _openFeed(event) {
        const index = event.model.__data.index;
        this.$.list.item = [
          ...this.feeds.slice(0, index),
          {
            ...object,
            class: 'new',
          },
          ...this.feeds.slice(index+1)
        ];

@Flamenco
Copy link
Contributor Author

@NicolasRannou Did you set set mutableData = true on your list?

@NicolasRannou
Copy link

NicolasRannou commented Mar 19, 2018

on the list itself, on the iron list, on the list of the iron-list?

@Flamenco
Copy link
Contributor Author

The iron list.

@NicolasRannou
Copy link

NicolasRannou commented Mar 19, 2018

Hmmm no success on that... odd...

To clarify, you use this approach to update a property of one object of the list:

this.$.list.items = [
  ...oldList.slice(0, i),
  {
    ...oldObjAtI,
    changedProp
  },
  ...oldList.slice(i+1)
];

@Flamenco
Copy link
Contributor Author

I think I used the polymer data api to update the data in the list, with the new immutable object

this.set(`filteredItems.5`, clone);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants