it-swarm.com.de

Wie setze ich programmgesteuert den Fokus auf dynamisch erstelltes FormControl in Angular2

Ich kann mich anscheinend nicht auf ein Eingabefeld in der dynamisch hinzugefügten FormGroup konzentrieren:

addNewRow(){
    (<FormArray>this.modalForm.get('group1')).Push(this.makeNewRow());
    // here I would like to set a focus to the first input field
    // say, it is named 'textField'

    // but <FormControl> nor [<AbstractControl>][1] dont seem to provide 
    // either a method to set focus or to access the native element
    // to act upon
}

Wie setze ich den Fokus auf angle2 FormControl oder AbstractControl?

14
user776686

Sie können nicht auf FormControl oder AbstractControl setzen, da es sich nicht um DOM-Elemente handelt. Was Sie tun müssen, ist, einen Elementverweis auf sie zu haben und .focus() aufzurufen. Sie können dies durch ViewChildren erreichen (von dem die API-Dokumente derzeit nicht vorhanden sind, 2016-12-16).

In Ihrer Komponentenklasse:

import { ElementRef, ViewChildren } from '@angular/core';

// ...imports and such

class MyComponent {
    // other variables
    @ViewChildren('formRow') rows: ElementRef;

    // ...other code
    addNewRow() {
        // other stuff for adding a row
        this.rows.first().nativeElement.focus();
    }
}

Wenn Sie sich auf das letzte Kind konzentrieren wollten ...this.rows.last().nativeElement.focus()

Und in Ihrer Vorlage so etwas wie:

<div #formRow *ngFor="let row in rows">
    <!-- form row stuff -->
</div>

BEARBEITEN:

Ich habe tatsächlich einen CodePen von jemandem gefunden, der tut, wonach Sie suchen https://codepen.io/souldreamer/pen/QydMNG

16
gonzofish

Kombinieren Sie für Angular 5 alle obigen Antworten wie folgt:

Komponentenrelevanter Code:

 import { AfterViewInit, QueryList, ViewChildren, OnDestroy } from '@angular/core';
 import { Subscription } from 'rxjs/Subscription';

 // .. other imports

 export class MyComp implements AfterViewInit, OnDestroy {
   @ViewChildren('input') rows: QueryList<any>;
   private sub1:Subscription = new Subscription();
   //other variables ..

 // changes to rows only happen after this lifecycle event so you need
 // to subscribe to the changes made in rows.  
 // This subscription is to avoid memory leaks
 ngAfterViewInit() {
   this.sub1 = this.rows.changes.subscribe(resp => {
     if (this.rows.length > 1){
       this.rows.last.nativeElement.focus();
     }
   });
  }

  //memory leak avoidance
  ngOnDestroy(){
    this.sub1.unsubscribe();
  }


   //add a new input to the page
   addInput() {
     const formArray = this.form.get('inputs') as FormArray;

     formArray.Push(
        new FormGroup(
        {input: new FormControl(null, [Validators.required])}
     ));
    return true;
   }

 // need for dynamic adds of elements to re 
 //focus may not be needed by others
 trackByFn(index:any, item:any){
    return index;
 }

Die Template-Logik sieht folgendermaßen aus:

 <div formArrayName="inputs" class="col-md-6 col-12" 
     *ngFor="let inputCtrl of form.get('phones').controls; 
             let i=index; trackBy:trackByFn">
     <div [formGroupName]="i">
        <input #input type="text" class="phone" 
             (blur)="addRecord()"
             formControlName="input" />
     </div>
 </div>

In meiner Vorlage füge ich einen Datensatz zum Thema Unschärfe hinzu, aber Sie können genauso einfach eine Schaltfläche einrichten, um das nächste Eingabefeld dynamisch hinzuzufügen. Der wichtige Teil ist, dass mit diesem Code das neue Element den gewünschten Fokus erhält.

Lass mich wissen was du denkst

7
Ken

Dies ist die sichere Methode, die von Angular empfohlen wird

@Component({
  selector: 'my-comp',
  template: `
    <input #myInput type="text" />
    <div> Some other content </div>
  `
})
export class MyComp implements AfterViewInit {
  @ViewChild('myInput') input: ElementRef;

  constructor(private renderer: Renderer) {}

  ngAfterViewInit() {
    this.renderer.invokeElementMethod(this.input.nativeElement,    
    'focus');
  }
}
1
Omkar Yadav