Reputation: 39
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
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.
Upvotes: 1
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
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
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