Polymer 1.0 array splice is deleting the wrong item in array

1.1k views Asked by At

I am trying to create a simple to do list in Polymer, and I have the add portion working. When I click the "delete" icon next to the item, it deletes the most recently added item instead of the one that it should delete. It looks like it's getting the wrong index of the array, and I'm not sure how to fix it? Thanks!

<dom-module id="my-todo-list">
<template>

<div class="card">

  <div class="form">
    <paper-input label="Task" value="{{todo.task}}"></paper-input>
    <paper-button raised on-tap="_addTodo">Add Todo</paper-button>
  </div>

  <template is="dom-repeat" items="{{todos}}">
    <paper-card class="todos">
      <paper-checkbox id="checkTodo" on-click="_completeTodo"></paper-checkbox>
      <p>{{item.task}}</p>
      <iron-icon icon="delete" on-tap="_destroyAction"></iron-icon>
    </paper-card>
  </template>

</div>

</template>

<script>
Polymer({
  is: 'my-todo-list',

  properties: {
    todo: {
      type: Object,
      value: function() {
        return {};
      }
    },
    todos: {
      type: Array,
      value: function() {
        return [];
      }
    }
  },

  _addTodo: function() {
    console.log(this.todo);
    this.push('todos', this.todo);
    // this.todo = {};
  },

  _destroyAction: function(todo) {
    var index = this.todos.indexOf(todo);
    this.splice('todos', index, 1);
  },
});
 </script>
</dom-module>
2

There are 2 answers

1
Supersharp On BEST ANSWER

The first issue is that you always insert the same reference to the object this.todo in your _addTodo() method. Instead you should make a copy of the object. You sould also add an ID to differentiate it from the other items.

  _addTodo: function() {
    var copy = Object.assign({}, this.todo);    
    copy.id = this.push('todos', copy);
    // this.todo = {};
  }

Then you sould add the same ID in the HTML template:

<paper-card class="todos" id="{{item.id}}">

Now you can modify the _destroyAction() method to find the right element in the array, using Array.findIndex() method and Event.target property:

  _destroyAction: function(ev) {
    var index = this.todos.findIndex( function(item) { 
        return item.id == ev.target.parentElement.id 
    } );
    this.splice('todos', index, 1);
  }
0
demux On

Array.prototype.indexOf does not work for looking up objects. You can use a utility library like lodash or Array.prototype.find. It's not supported in all browsers though, so make sure to include a polyfill. Both find in lodash and the native one take a callback function as an argument.