Как использовать Angular4 для установки фокуса с помощью идентификатора элемента
Я новичок в Angular, и я пытаюсь использовать его, чтобы установить фокус на вход с идентификатором "input1". Я использую следующий код:
@ViewChild('input1') inputEl: ElementRef;
потом в компоненте:
this.inputEl.nativeElement.focus();
Но это не работает. Что я делаю неправильно? Любая помощь будет высоко ценится.
Ответы
Ответ 1
Один из ответов на вопрос, на который ссылается @Z.Bagley, дал мне ответ. Мне пришлось импортировать Renderer2 из @angular/core в мой компонент. Затем:
const element = this.renderer.selectRootElement('#input1');
// setTimeout(() => element.focus, 0);
setTimeout(() => element.focus(), 0);
Спасибо @MrBlaise за решение!
Ответ 2
составная часть
import { Component, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
...
@ViewChild('input1') inputEl:ElementRef;
ngAfterViewInit() {
setTimeout(() => this.inputEl.nativeElement.focus());
}
HTML
<input type="text" #input1>
Ответ 3
Вот директива Angular4+, которую вы можете повторно использовать в любом компоненте. На основе кода, приведенного в ответе Ниль Т в этом вопросе.
import { NgZone, Renderer, Directive, Input } from '@angular/core';
@Directive({
selector: '[focusDirective]'
})
export class FocusDirective {
@Input() cssSelector: string
constructor(
private ngZone: NgZone,
private renderer: Renderer
) { }
ngOnInit() {
console.log(this.cssSelector);
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this.renderer.selectRootElement(this.cssSelector).focus();
}, 0);
});
}
}
Вы можете использовать его в шаблоне компонента следующим образом:
<input id="new-email" focusDirective cssSelector="#new-email"
formControlName="email" placeholder="Email" type="email" email>
Дайте ввод id и передайте id в свойство cssSelector
директивы. Или вы можете передать любой понравившийся вам cssSelector.
Комментарии от Niel T:
Поскольку единственное, что я делаю, - это сосредоточиться на элементе, мне не нужно заниматься детекцией изменений, поэтому я могу фактически запустить вызов renderer.selectRootElement вне Angular. Поскольку мне нужно предоставить время для рендеринга новых секций, секция элемента завершается в тайм-аут, чтобы разрешить время потоков рендеринга до того, как будет предпринята попытка выбора элемента. После того, как все это будет установлено, я могу просто вызвать элемент с помощью основных селекторов CSS.
Ответ 4
Это помогло мне (в ионной, но идея такая же) https://mhartington.io/post/setting-input-focus/
в шаблоне:
<ion-item>
<ion-label>Home</ion-label>
<ion-input #input type="text"></ion-input>
</ion-item>
<button (click)="focusInput(input)">Focus</button>
в контроллере:
focusInput(input) {
input.setFocus();
}
Ответ 5
Вот директива, которую вы можете использовать в любом компоненте:
import { NgZone, Directive, ElementRef, AfterContentInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[appFocus]'
})
export class FocusDirective implements AfterContentInit {
constructor(private el: ElementRef, private zone: NgZone, private renderer: Renderer2) {}
ngAfterContentInit() {
this.zone.runOutsideAngular(() => setTimeout(() => {
this.renderer.selectRootElement(this.el.nativeElement).focus();
}, 0));
}
}
Использование:
<input type="text" appFocus>
Ответ 6
Я также сталкиваюсь с такой же проблемой после некоторого поиска, я нашел хорошее решение, поскольку @GreyBeardedGeek означало, что setTimeout является ключом этого решения. Он абсолютно прав. В вашем методе вам просто нужно добавить setTimeout, и ваша проблема будет решена.
setTimeout(() => this.inputEl.nativeElement.focus(), 0);