В Angular2 как установить привязку для фокуса элемента. Я не хочу устанавливать его с помощью elementRef. Я думаю, что в AngularJS существует директива ngFocus В Angular2 нет такой директивы
Как установить фокус на элемент со связыванием?
Ответ 1
Служба рендеринга теперь устарела (начиная с Angular 4.x) Новый сервис Renderer2 не имеет invokeElementMethod. Что вы можете сделать, это получить ссылку на элемент, подобный этому:
const element = this.renderer.selectRootElement('#elementId');
И затем вы можете использовать это, чтобы сосредоточиться на этом элементе следующим образом:
element.focus();
Подробнее о том, как работает selectRootElement, здесь:
EDIT:
Если элемент не фокусируется, общая проблема заключается в том, что элемент не готов. (например: отключено, скрыто и т.д.). Вы можете сделать это:
setTimeout(() => element.focus(), 0);
Это создаст макрозадачу, которая будет выполняться в следующем обороте виртуальной машины, поэтому, если вы включили элемент, фокус будет работать правильно.
Ответ 2
Простая директива по фокусировке
import {Directive, Input, ElementRef} from 'angular2/core';
@Directive({
    selector: '[focus]'
})
class FocusDirective {
    @Input()
    focus:boolean;
    constructor(@Inject(ElementRef) private element: ElementRef) {}
    protected ngOnChanges() {
        this.element.nativeElement.focus();
    }
}
// Usage
@Component({
    selector : 'app',
    template : '
        <input [focus]="inputFocused" type="text">
        <button (click)="moveFocus()">Move Focus</button>
    ',
    directives: [FocusDirective]
})
export class App {
    private inputFocused = false;
    moveFocus() {
        this.inputFocused = true;
        // we need this because nothing will 
        // happens on next method call, 
        // ngOnChanges in directive is only called if value is changed,
        // so we have to reset this value in async way,
        // this is ugly but works
        setTimeout(() => {this.inputFocused = false});
    }
}
Ответ 3
Я пробовал оба варианта, но никто не подходит для простого использования. 1st (by @AngJobs) нуждается в дополнительной работе в компоненте, где вы используете директиву (для установки focus = true), 2nd (by @ShellZero) не работает вообще, потому что фокус, вызываемый до того, как представление действительно готово. Поэтому я переместил фокус на ngAfterViewInit. Теперь вы можете просто добавить <input focus... и забыть об этом. Элемент автоматически получит фокус после автоматического просмотра.
import { Directive, ElementRef, Renderer, AfterViewInit } from '@angular/core';
@Directive({
    selector: '[focus]'
})
export class DmFocusDirective implements AfterViewInit {
    constructor(private _el: ElementRef, private renderer: Renderer) {
    }
    ngAfterViewInit() {
        this.renderer.invokeElementMethod(this._el.nativeElement, 'focus');
    }
}
Ответ 4
Лучшим способом настройки фокуса на элемент с помощью angular2 является использование Renderer и вызов метода для элемента. Нет способа сделать это без elementRef.
В результате получается примерно следующее:
this.renderer.invokeElementMethod(this.input.nativeElement, 'focus', []);
Где Renderer вводится в конструктор с помощью protected renderer : Renderer
Ответ 5
Гораздо проще:
import { Directive, ElementRef, Renderer} from "@angular/core";
@Directive({
    selector: "[Focus]"
})
export class myFocus {
    constructor(private _el: ElementRef, private renderer: Renderer) {
        this.renderer.invokeElementMethod(this._el.nativeElement, 'focus');
    }
}
Ответ 6
Он работает для меня, но имеет ошибки в консоли. После отладки и поиска найдена эта статья: https://www.picnet.com.au/blogs/guido/post/2016/09/20/angular2-ng2-focus-directive/
Просто скопируйте-вставьте. Это отлично сработало для меня.
import {Directive, AfterViewInit, ElementRef, DoCheck} from '@angular/core';
@Directive({selector: '[focus]'})
export class FocusDirective implements AfterViewInit, DoCheck {
    private lastVisible: boolean = false;
    private initialised: boolean = false;
    constructor(private el: ElementRef) {
    }
    ngAfterViewInit() {
        console.log('inside FocusDirective.ngAfterViewInit()');
        this.initialised = true;
        this.ngDoCheck();
    }
    ngDoCheck() {
        console.log('inside FocusDirective.ngDoCheck()');
        if (!this.initialised) {
            return;
        }
        const visible = !!this.el.nativeElement.offsetParent;
        if (visible && !this.lastVisible) {
            setTimeout(() => {
                this.el.nativeElement.focus();
            }, 1);
        }
        this.lastVisible = visible;
    }
}
Ответ 7
От @MrBlaise я взял фрагмент setTimeout, который сделал для меня следующую работу.
<input type="text" #searchInput />
import { ElementRef, ViewChild } from '@angular/core';
...
@ViewChild('searchInput') private searchInput: ElementRef;
...
setTimeout(() => this.searchInput.nativeElement.focus(), 0);
Ответ 8
import { Directive, ElementRef, AfterViewChecked } from '@angular/core';
@Directive({
 selector: '[autoFocus]',
})
export class FocusDirective implements AfterViewChecked {
  constructor(private _elementRef: ElementRef) { }
  ngAfterViewChecked() {
    this._elementRef.nativeElement.focus()
  }
}
Ответ 9
Хитрость заключается в том, чтобы использовать оба фокуса и выбирать вместе:
. Этот (элемент).nativeElement.focus(); . Этот (элемент).nativeElement.select();
