How to set focus on element with binding?

后端 未结 9 937
南方客
南方客 2020-12-09 10:23

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

相关标签:
9条回答
  • 2020-12-09 10:27

    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.

    0 讨论(0)
  • 2020-12-09 10:28

    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);
    
    0 讨论(0)
  • 2020-12-09 10:32

    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');
        }
    
    }
    
    0 讨论(0)
  • 2020-12-09 10:40

    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});
        }
    }
    
    0 讨论(0)
  • 2020-12-09 10:40
    import { Directive, ElementRef, AfterViewChecked } from '@angular/core';
    
    @Directive({
     selector: '[autoFocus]',
    })
    export class FocusDirective implements AfterViewChecked {
    
      constructor(private _elementRef: ElementRef) { }
    
      ngAfterViewChecked() {
        this._elementRef.nativeElement.focus()
      }
    
    }
    
    0 讨论(0)
  • 2020-12-09 10:41

    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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题