2016-03-04 13 views
32

私はAngular2(Beta 8)でコンポーネントを開発しています。コンポーネントには、テキストボックスとドロップダウンがあります。私は、コンポーネントがロードされるとすぐにテキストボックスにフォーカスを設定したい、またはドロップダウンの変更イベントに設定したいと思います。私はこれをangular2でどのように達成するでしょうか?以下はコンポーネントのHtmlです。Angular2 - コンポーネント負荷にテキストボックスをフォーカスする

<div> 
 
    <form role="form" class="form-horizontal ">   
 
     <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Name</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <input id="name" type="text" [(ngModel)]="person.Name" class="form-control" /> 
 

 
       </div> 
 
       <div class="col-md-2 col-sm-2"> 
 
        <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" /> 
 
       </div> 
 
      </div> 
 
     </div> 
 
     <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Person</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <select [(ngModel)]="SelectedPerson.Id" (change)="PersonSelected($event.target.value)" class="form-control"> 
 
         <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option> 
 
        </select> 
 
       </div> 
 
      </div> 
 
     </div>   
 
    </form> 
 
</div>

答えて

33

この回答は、ローカルのテンプレート変数名を宣言Angular2

  1. あなたのコンポーネントでインポートViewChildren

    import { Input, Output, AfterContentInit, ContentChild,AfterViewInit, ViewChild, ViewChildren } from 'angular2/core'; 
    
  2. をHTML要素にフォーカスを設定するには、ポストAngular 2: Focus on newly added input element

    手順に触発されましたフォーカスを設定するHTMLの場合

  3. には、以下の
  4. を(関数ngAfterViewInitを実装)、または他の適切なライフサイクルフック私は

    ngAfterViewInit() {vc.first.nativeElement.focus()} 
    
  5. フォーカスを設定するために使用されるコードの一部は、アクセスするDOM要素へ#input属性を追加しています。

///This is typescript 
 
import {Component, Input, Output, AfterContentInit, ContentChild, 
 
    AfterViewChecked, AfterViewInit, ViewChild,ViewChildren} from 'angular2/core'; 
 

 
export class AppComponent implements AfterViewInit,AfterViewChecked { 
 
    @ViewChildren('input') vc; 
 
    
 
    ngAfterViewInit() {    
 
     this.vc.first.nativeElement.focus(); 
 
    } 
 
    
 
}
<div> 
 
    <form role="form" class="form-horizontal ">   
 
     <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Name</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <input #input id="name" type="text" [(ngModel)]="person.Name" class="form-control" /> 
 

 
       </div> 
 
       <div class="col-md-2 col-sm-2"> 
 
        <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" /> 
 
       </div> 
 
      </div> 
 
     </div> 
 
     <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Person</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <select [(ngModel)]="SelectedPerson.Id" (change)="PersonSelected($event.target.value)" class="form-control"> 
 
         <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option> 
 
        </select> 
 
       </div> 
 
      </div> 
 
     </div>   
 
    </form> 
 
</div>

+2

十分単純ですが、別のコンポーネントでフォーカスを設定する必要がある場合はどうなりますか?たとえば、子コンポーネントのデフォルト検索ボックス(ヘッダー内)。 –

+1

動的に生成される要素はどうですか? –

4

フォーカスを設定する方法についてはAngular 2: Focus on newly added input elementを参照してください。

"ロード中"の場合は、ngAfterViewInit()ライフサイクルコールバックを使用してください。

+0

ありがとうございます。あなたが共有したリンクはかなり役に立ちました。これは+1です。この特定のシナリオの答えを共有します。 – parag

15

元の質問には、最初にフォーカスを設定するには、ORイベントに応答して、後に注力設定する方法を求めました。これにアプローチする正しい方法は、任意の入力要素に設定できる属性ディレクティブを作成し、この入力要素のフォーカスメソッドを安全にトリガするカスタムイベントを使用することです。それは安全なウェブワーカーであるnativeElement、上renderer.invokeElementMethodを使用していること

import { Directive, Input, EventEmitter, ElementRef, Renderer, Inject } from '@angular/core'; 

@Directive({ 
    selector: '[focus]' 
}) 
export class FocusDirective { 
    @Input('focus') focusEvent: EventEmitter<boolean>; 

    constructor(@Inject(ElementRef) private element: ElementRef, private renderer: Renderer) { 
    } 

    ngOnInit() { 
     this.focusEvent.subscribe(event => { 
      this.renderer.invokeElementMethod(this.element.nativeElement, 'focus', []); 
     }); 
    } 
} 

注:そう、最初のディレクティブを作成します。また、focusEventが入力として宣言されていることにも注意してください。

public focusSettingEventEmitter = new EventEmitter<boolean>(); 

ngAfterViewInit() { // ngOnInit is NOT the right lifecycle event for this. 
    this.focusSettingEventEmitter.emit(true); 
} 
setFocus(): void { 
    this.focusSettingEventEmitter.emit(true); 
} 

の上に持つEventEmitterをインポートすることを忘れないでください:

は、その後、あなたが入力要素にフォーカスを設定するために、新しいディレクティブを使用したいテンプレートを持つ角度2コンポーネントに次の宣言を追加しますこのようなコンポーネント:

<input id="name" type="text" name="name" 
    [(ngModel)]="person.Name" class="form-control" 
    [focus]="focusSettingEventEmitter"> 
:このコンポーネントの

import { Component, EventEmitter } from '@angular/core'; 

とテンプレートでは、このような新しい[フォーカス]属性を設定します

最後に、あなたのモジュールでは、このような新しいディレクティブのインポートと宣言:要約すると

import { FocusDirective } from './focus.directive'; 

@NgModule({ 
    imports: [ BrowserModule, FormsModule ], 
    declarations: [AppComponent, AnotherComponent, FocusDirective ], 
    bootstrap: [ AppComponent ] 
}) 

を:ngAfterViewInit機能は、新しい持つEventEmitterを発するようになります、と私たちは、[フォーカス]に、このエミッタを割り当てるので、このディレクティブへの入力としてこのEventEmitterを宣言し、このイベントへのサブスクリプションに渡したarrow関数でfocusメソッドを呼び出し、コンポーネントの後に入力要素にフォーカスが移ります初期化され、setFocusが呼び出されるたびに呼び出されます。

私は自分のアプリで同じ必要性がありました。これは広告として機能しました。以下にありがとうございました:http://blog.thecodecampus.de/angular-2-set-focus-element/

+0

これは素晴らしく、うまくいきますが、それはちょっとした問題ではありませんか?私はそれが要件ではないので、ユーザーのための素晴らしいこととしてそれをやろうとしていましたが、ユーザーを1回のクリックで保存するためのコードが過剰であるようです。 –

34

シンプルautofocus HTML5属性を使用して、私は少し異なるがあった

<input autofocus placeholder="enter text" [(ngModel)]="test"> 

または

<button autofocus (click)="submit()">Submit</button> 

http://www.w3schools.com/TAgs/att_input_autofocus.asp

+13

これは、ページを更新したりページを最初から読み込んだ場合にのみ機能します。ルータ経由でフォームコンポーネントに移動すると、フィールドは選択されません。 –

+4

これは完璧です。なぜ大砲で飛んでいくのですか? :D –

+0

複数のコンポーネントがある場合、これは良い解決策ではありません。これは、最初のデフォルトコンポーネントでのみ有効です –

2

'ロードオン' のシナリオのために働きます問題。私はモーダルの入力で働いて、それは私を怒らせた。提案されたソリューションのどれも私にとっては役に立たなかった。私はこの問題を見つけるまで

は:https://github.com/valor-software/ngx-bootstrap/issues/1597

これは良い男は私にNGX-ブートストラップモーダルは、フォーカス設定を持っていることをヒントを与えました。この設定がfalseに設定されていない場合、モーダルはアニメーションの後にフォーカスされ、何か他のものにフォーカスする必要はありません。

更新:

がモーダルのdivに次の属性を追加し、この構成を設定するには:

[config]="{focus: false}" 

アップデート2:

入力フィールドにフォーカスを強制的に私はディレクティブを書いて、入力フィールドがng-untouchedのクラスを持つ限り、すべてのAfterViewCheckedサイクルでフォーカスを設定しました。

ngAfterViewChecked() { 
    // This dirty hack is needed to force focus on an input element of a modal. 
    if (this.el.nativeElement.classList.contains('ng-untouched')) { 
     this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []); 
    } 
} 
+0

こんにちは@FireGnome、これを設定する場所を教えてください。 – cyberabis

+0

あなたがここに見ることができるよう: http://valor-software.com/ngx-bootstrap/#/modals#static 構成属性は、[設定] =「{背景: 『静的』}」がありますが 偽 – FireGnome

+0

こんにちは、私は同じ問題を抱えています、私はngxのモーダルと設定を追加し、ディレクティブ(まだ運がない)でフォーカスを追加しようとしましたが、何をフォーカスに追加しましたか?毎回入力?ありがとう – Simon