PolymerElements / iron-list

Element for a virtual, "infinite" list
https://www.webcomponents.org/element/PolymerElements/iron-list
219 stars 131 forks source link

List will not refresh when nested inside other element #450

Open Stefdv opened 7 years ago

Stefdv commented 7 years ago

Description

when i use an iron-list inside another customelement the list does not refresh when i change the items. ( completely replace the array for another array ) When the list is only one level deep it does work! main-app -> customcomponent with iron-list works main-app -> customcomponent-> customcomponent with iron-list fails

document.querySelector('iron-list').fire('iron-resize'); OR document.querySelector('iron-list').notifyResize() Does NOT refresh the list

Expected outcome

When list.items change the new items appear, the old ones are removed after notifyResize().

Actual outcome

When list.items change i see the new items but when the old array was longer the remaining (old) items stay visible. notifyresize does NOT refresh the list.

Browsers Affected

craPkit commented 7 years ago

Check your styles!

I have just encountered the same symptom while using iron-flex-layout classes on my top-level template content, which override the display property, no matter the state within iron-list. e.g.:

    <!-- markup -->
    <iron-list>
      <template>
        <div class="horizontal layout">...</div>
      </template>
    </iron-list>

    <!-- rendered result -->
     <iron-list>
      ...
        <!-- this is still visible: -->
        <div class="horizontal layout" hidden>...</div>
    </iron-list>

Background: <iron-list> uses the hidden attribute to "remove" its internal, unused (but previously rendered) _physicalItems (which, in turn, are stamped instances of your content template). Since that attribute induces display: hidden; with only a weak selector specificity you must be careful not override the display style on your iron-list content with something other than none.

czellweg commented 7 years ago

As described by @Stefdv, I had the same issue of the iron-list not being updated correctly, i.e. 'old' entries still showed up after having updated the underlying data-array.

The issue for me was disregarding this little gem: iron-list must be given a <template> which contains exactly one element (see documentation of iron-list).

The solution for me therefore was:

<style>
.item {
  @apply --layout-horizontal;
}
</style>
...
<iron-list
  id="searchResultList"
  items="[[data]]"
  selected-items="{{selectedItems}}"
  selection-enabled
  multi-selection>
  <template>
   <div> <=== this is important
     <div tabindex$="[[tabIndex]]" class$="item" aria-label$="Select/Deselect [[item.id]]">
        <div>[[item.id]]</div>
        <iron-icon icon="check-box"></iron-icon>
      </div>
      <div class="border"></div>
    </div>
  </template>
</iron-list>
MelHarbour commented 6 years ago

I think it's actually a combination of the two solutions mentioned above. You need to have only a single child of the <template> element, but also that element must not have any of (for example) the iron-flex-layout classes applied to it. So the following will fail to filter:

<style>
.item {
  @apply --layout-horizontal;
}
</style>
...
<iron-list items="[[data]]">
<template>
  <div class="item">[[item.id]]</div>
</template>
</iron-list>

Whereas this will work correctly:

<style>
.item {
  @apply --layout-horizontal;
}
</style>
...
<iron-list items="[[data]]">
<template>
  <div>
    <div class="item">[[item.id]]</div>
  </div>
</template>
</iron-list>