@ViewChild в скрытой форме возвращает неопределенное значение — как получить к нему доступ, чтобы я мог установить фокус

#javascript #angular #angular-forms

#javascript #угловой #угловые формы

Вопрос:

У меня есть форма, которая видна только при нажатии кнопки. Я хочу, чтобы пользователь нажал кнопку и переместил фокус на первое поле ввода после отображения формы.

Используя @Viewchild, я не могу этого сделать, потому что форма недоступна при первой загрузке компонента. Я получаю сообщение об ошибке Cannot read property 'nativeElement' of undefined

TS

 formLoaded = false;

@ViewChild("firstName") nameField: ElementRef;
editName(): void {
 this.formLoaded = true;
 this.nameField.nativeElement.focus();
}
  

HTML

 <button mat-raised-button color="primary" (click)="editName()">Edit</button>
 <div *ngIf="formLoaded" class="group">
  <mat-form-field>
   <input #firstName matInput>
  </mat-form-field>
</div>
  

Как я могу получить доступ к входному #FirstName, чтобы я мог сфокусировать его?

Упрощенная версия моего фактического кода находится здесь.

Ответ №1:

Используйте перехват жизненного цикла AfterViewChecked, он запускается каждый раз, когда срабатывает обнаружение изменений. Таким образом, только после того, как форма присутствует в шаблоне, вы установите для нее фокус.

 ngAfterViewChecked() {
   if (this.formLoaded) {
      this.nameField.nativeElement.focus();
   }
}
  

Удалите оператор focus из метода editName:

 @ViewChild("firstName") nameField: ElementRef;
editName(): void {
   this.formLoaded = true;
}
  

Комментарии:

1. Да, я заставил его работать с комбинацией ngAfterViewChecked и setTimeout . Без тайм-аута я получал «ExpressionChangedAfterItHasBeenCheckedError», я также изменил статическое значение на false в качестве второго аргумента @Viewchild.

Ответ №2:

Оберните метод фокусировки следующим образом:

  editName(): void {
        this.formLoaded = true;
        setTimeout(()=>{
          this.nameField.nativeElement.focus();
        })
     }
  

Другой способ — использовать сеттер

 @ViewChild("firstName",{read:MatInput}) set viewC(nameField: MatInput){
 if(nameField){
    nameField.focus();
 }
};
  

Разветвленный пример

Комментарии:

1. Поскольку вы размещаете ссылку на шаблон в matInput, он может ссылаться на ссылку matinput, попробуйте установить viewchild явно для ссылки на элемент следующим образом @ViewChild(«FirstName»,{read:ElementRef}) nameField: ElementRef;

2. Если вы консоль, что она печатает на консоли?

3. @ViewChild(«FirstName»,{read:MatInput}) nameField: MatInput; другой способ — получить экземпляр matInput и использовать метод фокусировки matinput, вы можете попробовать это?

4. Затем внутри метода EditForm вызывается следующим образом: this.nameField . фокус ();

5. Другим способом было бы использование setter вместе с viewchild @ViewChild(«FirstName»,{read:MatInput}) set ViewC(nameField: MatInput){ if(nameField){ nameField . focus(); } console.log(поле имени); };