Как сосредоточиться на поле?

Я обновил с 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');
  }
}