2

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

6
  • Have you played with .indexOf() before? Try debugging remove() function and see what all arguments it actually receives. Commented Oct 10, 2020 at 14:35
  • index is a number, inputs are array of boolean Commented Oct 10, 2020 at 14:38
  • Which version of Angular is in use? Commented Oct 10, 2020 at 14:40
  • Angular 10. on it Commented Oct 10, 2020 at 14:41
  • Use index as i syntax, as suggested in this thread Commented Oct 10, 2020 at 14:43

4 Answers 4

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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

2 Comments

didn't help me. Maybe I made something wrong. I have put the source here. stackblitz.com/edit/…
I have edited with an explanation of this issue you are having, hope this helps
0

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.

Comments

0

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']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.