web-dev-qa-db-ja.com

Angular4を使用して要素IDでフォーカスを設定する方法

私はAngularを初めて使用し、それを使用してID「input1」の入力にフォーカスを設定しようとしています。私は次のコードを使用しています:

@ViewChild('input1') inputEl: ElementRef;

その後、コンポーネントで:

 this.inputEl.nativeElement.focus();

しかし、それは機能していません。私は何を間違えていますか?どんな助けも大歓迎です。

24
Pismotality

@ Z.Bagleyが言及した質問の回答の1つが答えをくれました。 Renderer2を@ angular/coreからコンポーネントにインポートする必要がありました。次に:

const element = this.renderer.selectRootElement('#input1');

// setTimeout(() => element.focus, 0);
setTimeout(() => element.focus(), 0);

@MrBlaiseに解決策をありがとう!

17
Pismotality

コンポーネント

import { Component, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
... 

@ViewChild('input1') inputEl:ElementRef;

ngAfterViewInit() {
      setTimeout(() => this.inputEl.nativeElement.focus());
}

html

<input type="text" #input1>
41
Dmitry Grinko

以下は、任意のコンポーネントで使用できるディレクティブです。

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

つかいます:

<input type="text" appFocus>
2
ACDev

これは私を助けてくれました(イオンで、しかしアイデアは同じです) https://mhartington.io/post/setting-input-focus/

テンプレート内:

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

コントローラー内:

  focusInput(input) {
    input.setFocus();
  }

@GreyBeardedGeekがsetTimeoutがこのソリューションのキーであると言っていたので、私はいくつかの検索の後、同じ問題に直面しました。彼は完全に正しいです。メソッドにsetTimeoutを追加するだけで問題が解決します。

setTimeout(() => this.inputEl.nativeElement.focus(), 0);
1
Abhijeet

これは、任意のコンポーネントで再利用できるAngular4 +ディレクティブです。 この質問 のNiel Tによる回答で指定されたコードに基づきます。

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

次のようなコンポーネントテンプレートで使用できます。

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

入力にIDを与え、そのIDをディレクティブのcssSelectorプロパティに渡します。または、任意のcssSelectorを渡すことができます。

Niel Tからのコメント:

私がしているのは要素にフォーカスを設定することだけなので、変更の検出について心配する必要はありません。そのため、Angularの外でrenderer.selectRootElementの呼び出しを実際に実行できます。新しいセクションにレンダリングの時間を与える必要があるため、エレメントセクションはタイムアウトでラップされ、エレメントの選択が試行される前にレンダリングスレッドの時間が追いつくことができます。すべての設定が完了したら、基本的なCSSセレクターを使用して要素を呼び出すだけです。

1
rmcsharry