In Angular2 how can I set binding on element focus. I don\'t want to set it with elementRef. I think in AngularJS there is ngFocus directive In Angular2 there is no such dir
Renderer service is now deprecated (as of Angular 4.x) The new Renderer2 service doesn't have the invokeElementMethod. What you can do is to get a reference to the element like this:
const element = this.renderer.selectRootElement('#elementId');
And then you can use that to focus on that element like so:
element.focus();
More on how selectRootElement
works here:
EDIT:
If the element doesn't get focused the common issue is that the element is not ready. (eg.: disabled, hidden etc.). You can do this:
setTimeout(() => element.focus(), 0);
This will create a macrotask that will run in the next VM turn, so if you enabled the element the focus will run properly.
From @MrBlaise I took the setTimeout snippet which made the following work for me.
<input type="text" #searchInput />
import { ElementRef, ViewChild } from '@angular/core';
...
@ViewChild('searchInput') private searchInput: ElementRef;
...
setTimeout(() => this.searchInput.nativeElement.focus(), 0);
Much more simpler way:
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');
}
}
A simple 'focus' Directive
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});
}
}
import { Directive, ElementRef, AfterViewChecked } from '@angular/core';
@Directive({
selector: '[autoFocus]',
})
export class FocusDirective implements AfterViewChecked {
constructor(private _elementRef: ElementRef) { }
ngAfterViewChecked() {
this._elementRef.nativeElement.focus()
}
}
It works for me but have errors in console. After debugging and searching found this article: https://www.picnet.com.au/blogs/guido/post/2016/09/20/angular2-ng2-focus-directive/
Just copy-paste. It worked perfectly for me.
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;
}
}