How to set focus on element with binding?

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.


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});
    }
}

Tags:

Angular