Yurii
Yurii

Reputation: 39

Delete by index doesn't works. Angular

The following code always deletes the last element. I want to create input fields with the button delete at the same time. How can I delete the item by id?

TS:

public inputs: boolean[] = [];
  public addNew(): void {
    this.inputs.push(true);
  }

  public remove( index: number): void {
   this.inputs.splice(index, 1);
  }

HTML:

<div *ngFor="let item of inputs; let i = index" class="form-row mb-2">
   <input id="inputField{{i}}" type="text" class="form-control col-sm-9" name="inputField{{i}}" >
   <button (click)="remove(i)" type="button" class="btn btn-danger col-sm-offset-2 col-sm-2 ml-4">Remove</button>
</div>

https://stackblitz.com/edit/angular-twf9st?file=src%2Fapp%2Fapp.component.ts

Upvotes: 2

Views: 1298

Answers (4)

Owen Kelvin
Owen Kelvin

Reputation: 15083

You need to add a trackBy so that angular can know the element which was removed, something like

HTML

<div *ngFor="let item of inputs; let i = index" class="form-row mb-2" trackBy: customTB>
   <input id="inputField{{i}}" type="text" class="form-control col-sm-9" name="inputField{{i}}" >
   <button (click)="remove(i)" type="button" class="btn btn-danger col-sm-offset-2 col-sm-2 ml-4">Remove</button>
</div>

TS file add the below function

customTB(index, song) { return `${index}-${song.id}`; }

It is also important to note that angular will only update the UI in the *ngFor directive if the input change

Consider below.

You add the four elements to inputs and your inputs look like below

[true, true, true, true]

Lets Remove the 3rd Element

[true, true, true]

What if I was to remove the 1st Element instead of the 3rd

[true, true, true]

Since the input is the same after both removing the 1st and 3rd ELements, angular optimization will remove the last elemen,

Now Lets amend the code

TS

inputs: string[] = [];

    public addNew(): void {
    this.inputs.push('');
  }

  public remove( index: number): void {
   this.inputs.splice(index, 1);
   console.log(index);
  }

HTML

 <div class="form-row  pb-2">
   <input id="field_id" type="text" class="form-control col-sm-9" name="field_id"
              ngModel>
<button type="button" (click)="addNew()" [disabled]="inputs.length > 3" >+ Add</button>
</div>
<div *ngFor="let item of inputs; index as i" class="form-row mb-2">
  <input [(ngModel)]='inputs[i]' id="inputField{{i}}" type="text" name="inputField{{i}}" >
  <button (click)="remove(i)" type="button">Remove</button>
</div>

The above will work as long as the input is NOT the same. To ensure this always works, we add the trackBy.

Sample on Stackblitz

Upvotes: 1

Richard Hunter
Richard Hunter

Reputation: 2200

I think the Array.prototype.filter() function is the best way to do this:

let inputs = ['alpha', 'beta', 'gamma', 'delta'];
let index = 2
inputs = inputs.filter((input, i) => i !== index);
console.log(inputs); // ['alpha', 'beta', 'delta']

Upvotes: 0

Ganesh
Ganesh

Reputation: 6016

Issue is with the splice method not your code.

It's working with numbers or you can check with any object type other than boolean. Here splice is not working as expected in your case where it's not able locate the value to delete with index.

You can see in this: stackblitz

Upvotes: 1

RonCG
RonCG

Reputation: 369

Your code is working fine. Its not deleting the last element. Whats happening is that the splice method deletes the corresponding element in the array, and then the array length is updated accordingly. So, lets say that you have 4 elements in your array:

test = [0,1,2,3] //(using numbers just so its clearer)

Now I apply the splice method like this:

test.splice(2,1);

The result will be:

[0,1,3]

The element in the corresponding index was deleted, but the lenght of my array also changed (I have one less element now). Once this happens, angular updates the dom with the remaining elements of your array. It just looks like its deleting the last element, but its not.

Upvotes: 0

Related Questions