I am trying to delete an item from iron-list
using the following code.
my-element.html
<iron-list id="list" items="[[items]]" as="item"
selected-items="{{selectedItems}}"
selection-enabled multi-selection>
<template>
<my-item item="[[item]]" on-tap="_onItemTap"></my-item>
</template>
</iron-list>
...
_onItemTap: function(e) {
this.items.splice(e.model.index, 1);
}
Expected behavior
- Tap list item
- List item disappears
- Select next list item
- Next list item is selected
Actual behavior
- Tap list item
- List item does not disappear
- Select same list item (i.e., the one previously intended to be deleted)
- Next list item is actually selected (i.e., index offset by one)
Questions
- What code will result in the desired / expected behavior?
- Please provide a working jsBin sample.
See this answer for specific syntax contributing to the problem.
Here is a working JSBin.
http://jsbin.com/qefemoloxi/1/edit?html,console,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-button/paper-button.html" rel="import">
<link href="iron-list/iron-list.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style>
iron-list {
height: 100vh;
}
</style>
<iron-list id="list" items="[[items]]" as="item">
<template>
<paper-button on-tap="_deleteItem">[[item.name]]</paper-button>
</template>
</iron-list>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
items: {
type: Array,
value: function() {
return [
{ 'name':'foo' },
{ 'name':'bar' },
{ 'name':'qux' },
{ 'name':'baz' },
{ 'name':'quux'}
]
}
}
},
_deleteItem: function(e) {
console.log(e.model.index);
this.splice('items', e.model.index, 1);
this.$.list.fire('resize');
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
A summary of this page suggests this documentation as follows:
Question
app.removeItem = function(index) {
app.data.splice(index, 1);
console.log("Removing " + index);
document.querySelector('#tobuy').fire('resize');
};
Reply
document.querySelector('#tobuy').push('items', {name: "Foo"})
then you don't need to call resize.
ref: https://www.polymer-project.org/1.0/docs/devguide/properties.html#array-observation
This documentation on array mutation provides the following boilerplate code:
custom-element.html
<dom-module id="custom-element">
<template>
<template is="dom-repeat"></template>
</template>
<script>
Polymer({
is: 'custom-element',
addUser: function(user) {
this.push('users', user);
},
removeUser: function(user) {
var index = this.users.indexOf(user);
this.splice('users', index, 1);
}
});
</script>
</dom-module>
Applying that to this case:
my-element.html
// As a syntactical matter, replace the following line
// this.items.splice(e.model.index, 1);
// With this line
this.splice('items', e.model.index, 1);
this.$.list.fire('resize');
A problem with this solution, however, is that it deletes the last item from the iron-list
, not the item at the expected index. In other words, it behaves like one would expect this.items.pop()
.
It also throws the following curious error message:
console.log
Uncaught TypeError: <item> should be a valid item
See this answer for full code solution.
The problem here was caused by the fact that my item.html
file was setting and displaying properties outside the item.
property. So, when the iron-list.(this.)splice('items', e.model.index, 1);
array mutation method was called, the non item
properties were not being removed from the DOM.
Example:
my-list-item.html
this.set( 'name', this.item.foo.bar.qux); // This syntax caused the problem
this.set('item.name', this.item.foo.bar.qux); // This fixed the problem
my-iron-list.html
this.splice('items', e.model.index, 1);