Home > database >  How to update filtered array after deleting item in angular
How to update filtered array after deleting item in angular

Time:11-16

I am trying to delete an item from filtered list but it is not getting updated.

I am able to delete item without filtering.

html

<div >
      <input
        
        type="text"
        name="search"
        [(ngModel)]="searchText"
        autocomplete="off"
        placeholder="&#61442;  Start searching for a hero by id or name or country"
      />
    </div>
    <table >
      <thead>
        <tr>
          <th>Id</th>
          <th>Hero Name</th>
          <th>Country</th>
          <th>Delete</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let hero of heroes | filter: searchText; let index = index">
          <td>{{ hero.id }}</td>
          <td>{{ hero.name }}</td>
          <td>{{ hero.country }}</td>
          <td (click)="onDelete(index)"><button>Delete</button></td>
        </tr>
      </tbody>
    </table>

Ts file:

searchText;
  heroes = [
    { id: 11, name: 'Mr. Nice', country: 'India' },
    { id: 12, name: 'Narco', country: 'USA' },
    { id: 13, name: 'Bombasto', country: 'UK' },
    { id: 14, name: 'Celeritas', country: 'Canada' },
    { id: 15, name: 'Magneta', country: 'Russia' },
    { id: 16, name: 'RubberMan', country: 'China' },
    { id: 17, name: 'Dynama', country: 'Germany' },
    { id: 18, name: 'Dr IQ', country: 'Hong Kong' },
    { id: 19, name: 'Magma', country: 'South Africa' },
    { id: 20, name: 'Tornado', country: 'Sri Lanka' },
  ];

  onDelete(index) {
    this.heroes.splice(index, 1);
    console.log('deleted');
  }

UI is not updating only when something is searched in the searchbar.

Here is the reproducible example link

Thanks!

CodePudding user response:

The hero in the heros list is identified by a unique id, you can try to delete it by a unique id.

<div >
  <h1>{{ title }}</h1>
</div>
<div >
  <div >
    <div >
      <input
        
        type="text"
        name="search"
        [(ngModel)]="searchText"
        autocomplete="off"
        placeholder="&#61442;  Start searching for a hero by id or name or country"
      />
    </div>
    <table >
      <thead>
        <tr>
          <th>Id</th>
          <th>Hero Name</th>
          <th>Country</th>
          <th>Delete</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let hero of heroes | filter: searchText; let index = index">
          <td>{{ hero.id }}</td>
          <td>{{ hero.name }}</td>
          <td>{{ hero.country }}</td>
          <td (click)="onDelete(hero.id)"><button>Delete</button></td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'Angular Search Using ng2-search-filter';
  searchText;
  heroes = [
    { id: 11, name: 'Mr. Nice', country: 'India' },
    { id: 12, name: 'Narco', country: 'USA' },
    { id: 13, name: 'Bombasto', country: 'UK' },
    { id: 14, name: 'Celeritas', country: 'Canada' },
    { id: 15, name: 'Magneta', country: 'Russia' },
    { id: 16, name: 'RubberMan', country: 'China' },
    { id: 17, name: 'Dynama', country: 'Germany' },
    { id: 18, name: 'Dr IQ', country: 'Hong Kong' },
    { id: 19, name: 'Magma', country: 'South Africa' },
    { id: 20, name: 'Tornado', country: 'Sri Lanka' },
  ];

  onDelete(heroId: number) {
    console.log(heroId);
    this.heroes = this.heroes.filter((hero) => hero.id !== heroId);
    console.log('deleted');
  }
}

Example here

CodePudding user response:

The problem is that you use the current index as the parameter to delete the item. If you filter for "Germany" and try to delete this object, the index of this very object is then 0 instead of 6 and you delete the first item from the list ({ id: 11, name: 'Mr. Nice', country: 'India' }). A better approach is to use id to make sure you delete the right object from the array:

<tr *ngFor="let hero of heroes | filter: searchText">
    <td>{{ hero.id }}</td>
    <td>{{ hero.name }}</td>
    <td>{{ hero.country }}</td>
    <td (click)="onDelete(hero.id)"><button>Delete</button></td>
</tr>

Method:

onDelete(id) {
    this.heroes.splice(this.heroes.findIndex(h => h.id === id));
}

CodePudding user response:

Angular change detection works by reference. By using splice on your array, the original reference (memory address) is not modified.

You would be best to do something like the following:

onDelete(id: number) {
  this.heroes = this.heroes.filter(hero => hero.id !== id);
}

This would trigger the change detection.

In addition to that, you could add a trackBy function to your *ngFor so that the dom for the array is not rewritten in full when only one item changes.

CodePudding user response:

I have investigated the issue and found that whenever you are filtering the data it shows the data on 1st index and when you click the delete button it always delete the value on 0 index because the searched value was showing on index 0.

The solution is that you have to pass hero.id on clicking onDelete() function and pass the id in the parameter instead of index:

 <tbody>
    <tr *ngFor="let hero of heroes | filter: searchText; let index = index">
      <td>{{ hero.id }}</td>
      <td>{{ hero.name }}</td>
      <td>{{ hero.country }}</td>
      <td (click)="onDelete(hero.id)"><button>Delete</button></td>
    </tr>
  </tbody>

and then in ts file get the index base on id:

onDelete(id) {
let index = this.heroes.findIndex((x) => x.id == id);
this.heroes.splice(index, 1);
console.log('deleted');

}

It will solve the issue.

  • Related