How to focus the nth-child in *ngFor with a mutating array

Viewed 491

I have a list of items that are displayed it in my template with an *ngFor directive. An item in the array will be replaced, so it will be rerendered. I am trying to select a specific element in the *ngFor after this rerendering.

My first try

The code below works until an element is replaced from the array and the reference I used disappears.

my.component.html

<div *ngFor='let item of array'>
  <input #input type='text' [value]='item.name' \>
  <button (click)='select_function( input )'></button>
</div>

my.component.ts

@Component({
  // ...
})
export class MyComponent {
  public array: [] = [{name: 'Peter'}, {name: 'John'}]
  public select_function( element ) {
    element.focus();
  }
}

An incomplete solution

So I figured I should use the index somehow.

my.component.html

<div *ngFor='let item of array; let index = index;'>
  <input #input type='text' [value]='item.name' \>
  <button (click)='select_function(index)'>Modify</button>
</div>

my.component.ts

@Component({
  // ...
})
export class MyComponent {
  public array: [] = [{name: 'Peter'}, {name: 'John'}]
  public select_function( index) {
    // the array is mutated ( with ngrx in the actual situation )
    this.array.splice( index, 1, {name: 'Mary'} );
    // how do I get the nth element that was replaced from my template?
    // ???
    element.focus();
  }
}

How can I use the index to select a reference of the element in the view?

1 Answers

use ViewChildren and focus the last Element of the QueryList. Be carefull, It's possible you need "wait" Angular display the new data (for this use setTimeout)

//it's 'input' because your reference variable is #input
@ViewChildren('input',{read:ElementRef}) inputs:QueryList<ElementRef>

public select_function( index) {
    this.array.splice( index, 1, {name: 'Mary'} );
    setTimeout(()=>{
        //if you want the last element
        //inputs.last.nativeElement.focus()
        //if you want the nth
        inputs.find((x,i)=>i==index).nativeElement.focus()
    })
  }
Related