Как установить фокус на элемент со связыванием?

В 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();