0

I'm trying to move the focus from one input to the following one, they are created in pairs using form builder in Angular.

this.pesos.push(
            this.fb.group({
              peso: this.fb.control(""),
              nombre: this.fb.control("")
            })
          );

This code will generate two inputs more when pressing enter, and I'd like the first of it to be focused. However, if enter is pressed on the first of each pair, the focus should go to the second, instead of generating a new pair. So after trying different logics, I believe the best one is to find what is focused, and jump to the next input in the document.

 <div *ngFor="let peso of pesos.controls; let i = index" [formGroupName]="i" class="formsubconjuntohorizontal">

          <mat-card class="width100 formsubconjuntohorizontal spacebetween" style="background-color: #f8f8f8;">
              <mat-form-field>
                <mat-label>Peso</mat-label>
                <input
                  matInput
                  [style.color]="
                    pesos.at(i).get('peso').value > formulario.get('capacidad').value
                      ? 'red'
                      : 'black'
                  "
                  type="number"
                  formControlName="peso"
                  (keyup.enter)="FocusNext(i);"
                  autoFocus
                />
              </mat-form-field>
              <mat-form-field>
                <mat-label>Casa</mat-label>
                <input matInput type="text" formControlName="nombre" type="text" (keyup.enter)="FocusDown(i+1);" autoFocus/>
              </mat-form-field>
              <mat-card style="width: 40px;" (click)="deletePeso(i)" style="cursor:pointer; background-color: #ffebeb">
                <button type="button" mat-mini-fab color="primary" (click)="deletePeso(i)">
                  <mat-icon>delete_forever</mat-icon>
                </button>
              </mat-card>
          </mat-card>
        </div>

I'm trying to find something between document.activeElement and document.queryselectorAll('input'), but I don't know if that is the right way or if there is a easier way from form builder for this.

UPDATE

.ts file

 @ViewChildren('input') inputs:QueryList<ElementRef>
  ngAfterViewInit() {
    this.inputs.last && this.inputs.last.nativeElement.focus()
    this.numberOfInputs = this.inputs.length;
    this.inputs.changes.subscribe(() => {
      if (this.inputs.length)
        this.inputs.last.nativeElement.focus()
    })
  }

FocusDown(){
  this.pesos.push(
    this.fb.group({
      peso: this.fb.control(""),
      nombre: this.fb.control("")
    })
  );

 FocusNext(){
 document.querySelectorAll('input')[document.querySelectorAll('input').length-1].focus();
}

html file:

<mat-card class="width100 formsubconjuntohorizontal spacebetween" style="background-color: #f8f8f8;">
              <mat-form-field>
                <mat-label>Peso</mat-label>
                <input #input
                  matInput
                  [style.color]="
                    pesos.at(i).get('peso').value > formulario.get('capacidad').value
                      ? 'red'
                      : 'black'
                  "
                  type="number"
                  formControlName="peso"
                  (keyup.enter)="FocusNext();"
                  autoFocus
                />
              </mat-form-field>
              <mat-form-field>
                <mat-label>Casa</mat-label>
                <input matInput type="text" formControlName="nombre" type="text" (keyup.enter)="FocusDown();" autoFocus/>
              </mat-form-field>
              <mat-card style="width: 40px;" (click)="deletePeso(i)" style="cursor:pointer; background-color: #ffebeb">
                <button type="button" mat-mini-fab color="primary" (click)="deletePeso(i)">
                  <mat-icon>delete_forever</mat-icon>
                </button>
              </mat-card>
          </mat-card>

As for now, when enter is lifted, the first input focus goes to the second input focus. But when I do this in the second input gets the focus and loses it. I get also this error.

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'mat-form-field-should-float: false'. Current value: 'mat-form-field-should-float: true'.

Germán
  • 1,007
  • 1
  • 7
  • 20
  • https://stackoverflow.com/questions/62786384/set-focus-on-dynamically-created-input-on-angular/62788888#62788888 – Eliseo Jul 16 '20 at 18:07
  • For some reason this is not working for me. The array of inputs appear as 0 elements. – Germán Jul 17 '20 at 14:15
  • see where I put the "reference variable" in the first input in the response. NOTE: I called it "input", you can call as you want, A fool example in https://stackblitz.com/edit/angular-tq7utm?file=src/app/input-overview-example.html – Eliseo Jul 18 '20 at 18:14

1 Answers1

0

About my comment, you need use a template reference variable in the input you want focus

  <mat-form-field>
    <mat-label>Peso</mat-label>
    <!--see the reference variable, yes this  "#input"-->
    <input #input matInput ..../>
  </mat-form-field>
  <mat-form-field>
    <mat-label>Casa</mat-label>
    <input matInput .../>
  </mat-form-field>
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • See that I'm creating a group inside the array. It means each time 2 inputs are created. Isn't there an easier solution like (what comes now probably makes no sense): this.pesos.push( this.fb.group({ peso: this.fb.control("").focus, nombre: this.fb.control("") }) ); I'm very novice and have trouble understanding some parts of code. – Germán Jul 20 '20 at 09:35
  • If only put the reference variable to the first input, the QueryList only take account the first input, it's only about the .html – Eliseo Jul 20 '20 at 09:36
  • In your stackblitz ts code, I don't see where "#input" is being referenced. – Germán Jul 20 '20 at 09:39
  • `#input` is in the **.html**, is a template reference variable to can use ViewChildren. in the .ts you see `@ViewChildren('input')` – Eliseo Jul 20 '20 at 09:47