iron-list
iron-list copied to clipboard
List will not refresh when nested inside other element
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
- [X] Chrome
- [ ] Firefox
- [ ] Safari 9
- [ ] Safari 8
- [ ] Safari 7
- [ ] Edge
- [ ] IE 11
- [ ] IE 10
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
.
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>
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>