0
votes

Using Angular 4.0.2, I have an *ngFor creating input elements and updating an object array through an add button, but I'm trying to figure out how to update the objects' indeces once an item is removed from that array.

Currently, my ngFor looks like:

*ngFor = let name of names; let i = index

Then, my delete button has a (click) event:

(click)="removeRow(i, names)"

And the method looks like:

    removeRow(index:number, names:Names[]){
        names.splice(index,1);
        index--;
    }

But, when I go to update another input element in the array after removing an object, the indeces are incorrect. It appears that "let i = index" in the *ngFor does not decrement, and I apparently cannot just use:

(click)="removeRow(i, names); i--"
3
You don't need to decrement the index yourself, if you remove an item from the collection ngFor will display the updated items with a new index. Why do you send 'names' as a parameter to the remove function, you already have it in the class ?Adrian Fâciu

3 Answers

3
votes

You do not need to manually modify the index set by *ngFor. Angular takes care of it with its two-way data binding. When you modify your "names" array in your component, the view will update itself to reflect the changes, this includes the index on your *ngFor.

*ngFor:

*ngFor="let name of names; let i = index"

Click event:

(click)="removeRow(i)"

Component method:

removeRow(index:number){
    this.names.splice(index,1);
}

Notice that you do not need to pass your array from your view to your component since you already have it in the component.

Edit: Plunker

1
votes

Without seeing more of your code ... this is only a guess. But I assume you also have a names property of the component class?

Try not passing the names array into the method and instead just removing the element from the bound names property. Angular`s data binding should then take care of the rest.

Template:

<tr *ngFor='let product of products; let i = index'>
    <td>
        <img    [src]='product.imageUrl'
                [title]='product.productName | uppercase'
                (click)="removeRow(i)">
    </td>
</tr>

I had an image so used the click on that ... but it will work the same on a button.

Component class:

removeRow(index: number): void {
    this.products.splice(index,1);
}

Also, I displayed the value of "i" in the template using {{i}} and after deleting a row the "i" value is correctly adjusted for the new set of indices.

0
votes

Isn't i being passed by value into your remove row function? If so you'd have to decrement it in the same scope it exists (Within the ngFor loop).

Example: https://snook.ca/archives/javascript/javascript_pass