Angular 5を使用してフロントエンドアプリケーションを操作しています。検索ボックスを非表示にする必要がありますが、ボタンをクリックすると、検索ボックスが表示され、フォーカスされます。
StackOverflowで見つかったいくつかの方法をディレクティブなどで試しましたが、成功しません。
サンプルコードは次のとおりです。
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello</h2>
</div>
<button (click) ="showSearch()">Show Search</button>
<p></p>
<form>
<div >
<input *ngIf="show" #search type="text" />
</div>
</form>
`,
})
export class App implements AfterViewInit {
@ViewChild('search') searchElement: ElementRef;
show: false;
name:string;
constructor() {
}
showSearch(){
this.show = !this.show;
this.searchElement.nativeElement.focus();
alert("focus");
}
ngAfterViewInit() {
this.firstNameElement.nativeElement.focus();
}
検索ボックスがフォーカスに設定されていません。
どうやってやるの?
Show searchメソッドを次のように変更します
showSearch(){
this.show = !this.show;
setTimeout(()=>{ // this will make the execution after the above boolean has changed
this.searchElement.nativeElement.focus();
},0);
}
これにはhtml autofocusを使用する必要があります。
<input *ngIf="show" #search type="text" autofocus />
注:コンポーネントが永続化されて再利用される場合、フラグメントが最初に作成されたときにのみオートフォーカスされます。この問題は、domフラグメントがアタッチされたときにdomフラグメント内のautofocus属性をチェックするグローバルdomリスナーを使用し、それを再適用するか、JavaScriptを介してフォーカスすることで克服できます。
このディレクティブは、表示されるとすぐに要素内のテキストを即座にフォーカスして選択します。これには、場合によってはsetTimeoutが必要になる場合がありますが、あまりテストされていません。
import { Directive, ElementRef, OnInit } from '@angular/core';
@Directive({
selector: '[appPrefixFocusAndSelect]',
})
export class FocusOnShowDirective implements OnInit {
constructor(private el: ElementRef) {
if (!el.nativeElement['focus']) {
throw new Error('Element does not accept focus.');
}
}
ngOnInit(): void {
const input: HTMLInputElement = this.el.nativeElement as HTMLInputElement;
input.focus();
input.select();
}
}
そしてHTMLで:
<mat-form-field>
<input matInput type="text" appPrefixFocusAndSelect [value]="'etc'">
</mat-form-field>
これについて検討します(Angular 7 Solution)
入力[appFocus] = "focus" ....
import {AfterViewInit, Directive, ElementRef, Input,} from '@angular/core';
@Directive({
selector: 'input[appFocus]',
})
export class FocusDirective implements AfterViewInit {
@Input('appFocus')
private focused: boolean = false;
constructor(public element: ElementRef<HTMLElement>) {
}
ngAfterViewInit(): void {
// ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
if (this.focused) {
setTimeout(() => this.element.nativeElement.focus(), 0);
}
}
}
ブール値が変更された後に実行を行い、タイムアウトの使用を回避するには、次のようにします。
import { ChangeDetectorRef } from '@angular/core';
constructor(private cd: ChangeDetectorRef) {}
showSearch(){
this.show = !this.show;
this.cd.detectChanges();
this.searchElement.nativeElement.focus();
}