1

I'm learning Angular (v6 to be specific), and trying to build a simple to do list.

I'm able to add items to an array and display in a list but cannot figure out how to delete specific items on click of that item.

Current code deletes the entire array on click. Here's my code:

app.component.html

 <h1>To Do List</h1>
  <label for="">What do you need to to?</label>
  <input type="text" [(ngModel)]="listItem">
  <br>
  <button (click)="addToList()">Add</button>
  <hr>
  <ul>
    <li *ngFor="let toDo of toDoList" (click)="removeFromList($event)">{{ toDo }}</li>
  </ul>

app.component.ts

export class AppComponent {
  title = 'to-do-list-app';
  listItem = '';
  toDoList = [];

  addToList() {
    this.toDoList.push(this.listItem);
  }

  removeFromList(addedItem) {
    this.toDoList.splice(addedItem);
  }
Eric Nguyen
  • 926
  • 3
  • 15
  • 37

3 Answers3

8

Pass the item index to splice and specify that one item is to be removed:

<li *ngFor="let toDo of toDoList; let i = index" (click)="toDoList.splice(i, 1)">

See this stackblitz for a demo.

ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • Thanks! Although the below options also works, this is the more elegant approach. I just learned this index method, but did not think of it in this project. – Eric Nguyen Aug 27 '18 at 15:56
0

On your click function send the object you are removing:

<li *ngFor="let toDo of toDoList" (click)="removeFromList(toDo)">{{ toDo }}</li>

And in your function, find the index of the element, and then use splice to remove it

removeFromList(addedItem) {
    var index = this.toDoList.indexOf(addedItem);

    this.toDoList.splice(index, 1); // Removes one element, starting from index
}
Jorgel
  • 920
  • 3
  • 14
  • 28
  • This works. I was passing ($event) instead of (toDO) – Eric Nguyen Aug 27 '18 at 15:54
  • 1
    This is bad solution. You have indexes in ngFor, there is no need to find it with indexOf. You get performance overhead and bugs in case of duplicate items. – Ivan Aug 27 '18 at 18:19
0

Splice will remove the item from the array by index (and how many items you want to remove), not by value.

To work with arrays and collections, I would suggest to use https://underscorejs.org/ I know it may be an overkill for this problem, but will be useful for more complex scenarios.

You can add the library to your angular project by running the following command:

npm i underscore --save

You may want to also add the typings by running:

npm i @types/underscore --save-dev

Your app.component.ts would then look like

import { Component } from '@angular/core';
import * as _ from 'underscore';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'to-do-list-app';
  listItem = '';
  toDoList = [];

  addToList() {
    this.toDoList.push(this.listItem);
  }
  removeFromList(addedItem) {
    this.toDoList = _.without(this.toDoList, addedItem);
  }
}

And your app.component.html will look like:

<h1>To Do List</h1>
<label for="">What do you need to to?</label>
<input type="text" [(ngModel)]="listItem">
<br>
<button (click)="addToList()">Add</button>
<hr>
<ul>
  <li *ngFor="let toDo of toDoList" (click)="removeFromList(toDo)">{{ toDo }}</li>
</ul>
Santiago Robledo
  • 1,202
  • 12
  • 9