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