How to use Angular4 to set focus by element id

后端 未结 6 1451
無奈伤痛
無奈伤痛 2020-12-14 14:11

I am new to Angular, and am trying to use it to set focus on an input with the id \"input1\". I am using the following code:



        
相关标签:
6条回答
  • 2020-12-14 14:48

    One of the answers in the question referred to by @Z.Bagley gave me the answer. I had to import Renderer2 from @angular/core into my component. Then:

    const element = this.renderer.selectRootElement('#input1');
    
    // setTimeout(() => element.focus, 0);
    setTimeout(() => element.focus(), 0);
    

    Thank you @MrBlaise for the solution!

    0 讨论(0)
  • 2020-12-14 14:48

    Here is an Angular4+ directive that you can re-use in any component. Based on code given in the answer by Niel T in this question.

    import { NgZone, Renderer, Directive, Input } from '@angular/core';
    
    @Directive({
        selector: '[focusDirective]'
    })
    export class FocusDirective {
        @Input() cssSelector: string
    
        constructor(
            private ngZone: NgZone,
            private renderer: Renderer
        ) { }
    
        ngOnInit() {
            console.log(this.cssSelector);
            this.ngZone.runOutsideAngular(() => {
                setTimeout(() => {
                    this.renderer.selectRootElement(this.cssSelector).focus();
                }, 0);
            });
        }
    }
    

    You can use it in a component template like this:

    <input id="new-email" focusDirective cssSelector="#new-email"
      formControlName="email" placeholder="Email" type="email" email>
    

    Give the input an id and pass the id to the cssSelector property of the directive. Or you can pass any cssSelector you like.

    Comments from Niel T:

    Since the only thing I'm doing is setting the focus on an element, I don't need to concern myself with change detection, so I can actually run the call to renderer.selectRootElement outside of Angular. Because I need to give the new sections time to render, the element section is wrapped in a timeout to allow the rendering threads time to catch up before the element selection is attempted. Once all that is setup, I can simply call the element using basic CSS selectors.

    0 讨论(0)
  • 2020-12-14 14:55

    Here is a directive that you can use in any component:

    import { NgZone, Directive, ElementRef, AfterContentInit, Renderer2 } from '@angular/core';
    
    @Directive({
        selector: '[appFocus]'
    })
    export class FocusDirective implements AfterContentInit {
        constructor(private el: ElementRef, private zone: NgZone, private renderer: Renderer2) {}
    
        ngAfterContentInit() {
            this.zone.runOutsideAngular(() => setTimeout(() => {
                this.renderer.selectRootElement(this.el.nativeElement).focus();
            }, 0));
        }
    }
    

    Use:

    <input type="text" appFocus>
    
    0 讨论(0)
  • 2020-12-14 14:57

    I also face same issue after some search I found a good solution as @GreyBeardedGeek mentioned that setTimeout is the key of this solution.He is totally correct. In your method you just need to add setTimeout and your problem will be solved.

    setTimeout(() => this.inputEl.nativeElement.focus(), 0);
    
    0 讨论(0)
  • 2020-12-14 15:05

    component

    import { Component, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
    ... 
    
    @ViewChild('input1', {static: false}) inputEl:ElementRef;
    
    ngAfterViewInit() {
          setTimeout(() => this.inputEl.nativeElement.focus());
    }
    

    html

    <input type="text" #input1>
    
    0 讨论(0)
  • 2020-12-14 15:12

    This helped to me (in ionic, but idea is the same) https://mhartington.io/post/setting-input-focus/

    in template:

    <ion-item>
          <ion-label>Home</ion-label>
          <ion-input #input type="text"></ion-input>
    </ion-item>
    <button (click)="focusInput(input)">Focus</button>
    

    in controller:

      focusInput(input) {
        input.setFocus();
      }
    
    0 讨论(0)
提交回复
热议问题