Как сосредоточиться на поле?
Я обновил с Angular 2 до Angular 4 и в документах написано использовать Renderer2
вместо Renderer
который устарел.
Сейчас я смотрю на источник Renderer, но не могу найти способ вызвать метод focus()
как раньше.
Старый метод:
this.renderer.invokeElementMethod(element, 'focus', []);
Каков новый подход?
РЕДАКТИРОВАТЬ
Что, если элемент, на котором я фокусируюсь, получен через QuerySelector
?
Например:
let inputField = document.querySelectorAll('.dialog input');
if ( inputField[0] ) {
inputField[0].focus();
}
Так как он получен через QuerySelector
, метод focus()
него не существует.
Ответы
Ответ 1
invokeElementMethod
устарел и не вернется в новый рендерер. Чтобы установить фокус на элемент, вы можете просто использовать это сейчас:
element.nativeElement.focus();
Если вы используете document.querySelectorAll
, вы делаете что-то не angular, и вы должны найти другой способ сделать это. Если нет другого способа сделать это, то применяется тот же принцип. Метод focus()
- простой javascript, поэтому вы можете использовать его в angular2/typescript. Обязательно сделайте querySelectorAll
внутри крюка ngAfterViewInit
компонента:
ngAfterViewInit() {
let inputField: HTMLElement = <HTMLElement>document.querySelectorAll('.dialog input')[0];
inputField && inputField.focus();
}
Ответ 2
Также вы можете использовать метод selectRootElement Renderer2.
Например:
constructor(private renderer: Renderer2) {}
this.renderer.selectRootElement('#domElementId').focus()
где domElementId id = 'domElementId' в вашем html
Ответ 3
template reference variable :#inlineEditControl
<input #inlineEditControl class="form-control form-control-lg" [placeholder]="label">
@ViewChild('inlineEditControl') inlineEditControl: ElementRef; // input DOM element
this.inlineEditControl.nativeElement.focus();
Ответ 4
В настоящее время кажется, что эта задача не достижима без непосредственной модификации DOM. Как говорили другие, invokeElementMethod() устарел. Тем не менее, вы найдете проблемы с использованием selectRootElement, так как это не его целевая цель, и вы потеряете детей внутри вашего DIV. Вот ссылка на вопрос SO, который объясняет selectRootElement более подробно (поскольку документы angular являются ужасными):
Renderer multiple selectRootElement Issue (с предоставленным plnkr)
На данный момент, как представляется, единственный способ легко достичь вашей цели - использовать ссылочную переменную шаблона, дочерний элемент представления и ваш viewChild.nativeElement.focus() (хотя эта практика также не рекомендуется)
Существует также обходное решение, использующее FocusService, обнаруженное в этой проблеме GitHub: https://github.com/angular/angular/issues/15674
В этом выпуске Tytskyi упоминает, что вы можете реализовать FocusService и предоставлять различные реализации focus() на основе AppModuleBrowser и AppModuleServer. Я не уверен в деталях, как это работает, но это может быть единственный способ достичь этого без использования nativeElement в настоящее время.
Ответ 5
Если вы объявляете правильный тип вашего inputField
var, вы можете использовать любой селектор запросов JS.
Для случаев, объявляющих:
let inputField: HTMLInputElement = document.querySelector('.dialog input');
позволяет звонить
inputField.focus();
что это будет работать, и никакая ошибка TS не будет выброшена.
Ответ 6
Если вы используете Angular CDK, вы можете установить фокус, используя FocusMonitor.focusVia
метод, который является частью @angular/cdk/a11y
модуля специальных возможностей (A11yModule).
Таким образом, вы можете избежать любых манипуляций с DOM и вообще не ссылаться на nativeElement
.
import { FocusMonitor } from '@angular/cdk/a11y';
export class ExampleComponent implements AfterViewInit {
@ViewChild('elem', {static: false}) elemRef;
constructor(private focusMonitor: FocusMonitor) {
}
ngAfterViewInit() {
// Programmatically set focus. Focus source is 'program'.
this.focusMonitor.focusVia(this.elemRef, 'program');
}
}