1

I'm dynamically creating inputs with *ngFor. So, I would like to set focus on the last created input. Could someone help me?

This is my template code:

                <div class="col-6">
              <mat-card class="dataItens">
                <mat-card-header>
                  <mat-card-title>Itens de dados</mat-card-title>
                </mat-card-header>
                <mat-card-content>
                  <section *ngFor="let dataItem of elementaryProcess.dataItens; let i = index;">
                    <mat-form-field class="input-dataItens">
                      <input matInput [(ngModel)]="dataItem.name" name="dataItem{{ i }}" id="dataItem{{ i }}"
                             autocomplete="off"
                             [ngModelOptions]="{standalone: true}" class="input-dataItens"
                             (keyup.arrowDown)="dataItemOnKeyUp()"/>
                    </mat-form-field>
                    <button type="button" mat-icon-button (click)="removeDataItem(i)">
                      <mat-icon>delete</mat-icon>
                    </button>
                  </section>
                </mat-card-content>
                <mat-card-actions>
                  <form>
                    <!-- Add button -->
                    <button mat-stroked-button color="primary" type="button" (click)="addDataItem()">Adicionar
                    </button>
                    <!-- ngFor code -->
                  </form>
                </mat-card-actions>
              </mat-card>
            </div>

And this is the function I use to add the inputs:

  addDataItem() {
    this.elementaryProcess.dataItens.push(new DataItem());
  }
surendra kumar
  • 1,686
  • 11
  • 15

2 Answers2

2

Using ViewChildren and ViewChildren.changes. See this SO

I updated the stackblitz to focus using arrows keys. It's so simple than create a function

@ViewChildren('input') inputs: QueryList<ElementRef> //<--here declare our "inputs"
focusElement(index:number){
    const input=this.inputs.find((x,i)=>i==index)
    if (input)
      input.nativeElement.focus()
  }

And in the .html we ise keydown.arrowUp and keydown.arrowDown

<p *ngFor="let el of elements;let i=index">
  <input #input (keydown.arrowUp)="focusElement(i-1)"
                (keydown.arrowDown)="focusElement(i+1)" >
</p>

Updated, as Victor comments below, there's a problem when you has no items. It's because I forget check if there are inputs. So, when subscribe to inputs.changes we need check it

this.inputs.changes.pipe(takeWhile(()=>this.alive)).subscribe(() => {
  if (this.inputs.length)  //<--add this "if"
    this.inputs.last.nativeElement.focus()
})
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • It is the solution I adopted, but It partially works. When I delete all components and insert the first one again, it stop to focus. Here, an example: https://stackblitz.com/edit/set-focus-example – Victor Vidigal Ribeiro Jul 09 '20 at 21:20
  • @VictorVidigalRibeiro, I updated the answer, the problem was that I did'nt check if there are elements, so, if there are no elements, Angular give an error and the app crash, Thanks for the advertistment! – Eliseo Jul 10 '20 at 06:26
  • I don't know where the "updated" code should be placed. Could you create a example or rework the code to have it clear, please? – Germán Jul 17 '20 at 13:01
  • if you see the stackblitz https://stackblitz.com/edit/angular-uuvccb?file=src%2Fapp%2Fapp.component.ts, in ngAferViewInit is where I subscribe to "this.inputs.changes", the "updated code" is that I added `if (this.inputs.length)` – Eliseo Jul 18 '20 at 09:06
1

There are multiple ways to do it but this code is just using template

U can do it with ngFor last like this

<ng-container *ngFor="let item of [1,2,3]; last as isLast" >

<input *ngIf="!isLast"type="text">

<ng-container *ngIf="isLast" >
   <input type="text" #lastOne>
   {{lastOne.focus()}}
</ng-container>
</ng-container>

another way to do it like this.

<ng-container *ngFor="let item of [1,2,3]" >

<input  type="text" #lastOne>

{{lastOne.focus()}}
</ng-container>

feel free to choose

enter image description here enter image description here https://stackblitz.com/edit/angular-7-master-g3qsmt?file=src%2Fapp%2Fapp.component.html

hanan
  • 1,768
  • 1
  • 14
  • 19