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();
}
검색 창이 초점으로 설정되지 않았습니다.
어떻게 할 수 있습니까?
답변
쇼 검색 방법을 다음과 같이 수정하십시오.
showSearch(){
this.show = !this.show;
setTimeout(()=>{ // this will make the execution after the above boolean has changed
this.searchElement.nativeElement.focus();
},0);
}
답변
이를 위해 html 자동 초점 을 사용해야 합니다.
<input *ngIf="show" #search type="text" autofocus />
참고 : 구성 요소가 유지되고 재사용되는 경우 조각이 처음 연결될 때만 자동 초점이 적용됩니다. 이 문제는 dom 프래그먼트가 연결될 때 자동 초점 속성을 확인하는 전역 dom 리스너를 보유한 다음 다시 적용하거나 자바 스크립트를 통해 초점을 맞추면 극복 할 수 있습니다.
답변
이 지시문은 표시되는 즉시 요소의 텍스트에 초점을 맞추고 선택합니다. 경우에 따라 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)
input [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);
}
}
}
답변
이것은 setTimeout없이 Angular 8에서 작동합니다.
import {AfterContentChecked, Directive, ElementRef} from '@angular/core';
@Directive({
selector: 'input[inputAutoFocus]'
})
export class InputFocusDirective implements AfterContentChecked {
constructor(private element: ElementRef<HTMLInputElement>) {}
ngAfterContentChecked(): void {
this.element.nativeElement.focus();
}
}
설명 : 좋습니다. 다음과 같은 이유로 작동합니다. 변경 감지. setTimout이 작동하는 것과 같은 이유이지만 Angular에서 setTimeout을 실행하면 Zone.js를 우회하고 모든 검사를 다시 실행하며 setTimeout이 완료되면 모든 변경이 완료되기 때문에 작동합니다. 올바른 수명주기 후크 (AfterContentChecked)를 사용하면 동일한 결과에 도달 할 수 있지만 추가주기가 실행되지 않는다는 이점이 있습니다. 모든 변경 사항이 확인되고 전달되면 함수가 실행되고 AfterContentInit 및 DoCheck 후크 이후에 실행됩니다. 내가 틀렸다면 나를 바로 잡으십시오.
https://angular.io/guide/lifecycle-hooks 에서 하나 이상의 수명주기 및 변경 감지
업데이트 : Angular Material CDK, a11y-package를 사용하는 경우 더 나은 방법을 찾았습니다. 먼저 입력 필드가있는 구성 요소를 선언하는 모듈에서 A11yModule 을 가져옵니다 . 그런 다음 cdkTrapFocus 및 cdkTrapFocusAutoCapture 지시문을 사용하고 html에서 다음과 같이 사용하고 입력에 tabIndex를 설정합니다.
<div class="dropdown" cdkTrapFocus cdkTrapFocusAutoCapture>
<input type="text tabIndex="0">
</div>
위치 지정 및 응답 성과 관련하여 드롭 다운에 몇 가지 문제가 있었고 대신 cdk에서 OverlayModule을 사용하기 시작했으며 A11yModule을 사용하는이 방법은 완벽하게 작동합니다.
답변
Angular에서는 HTML 자체에서 버튼 클릭시 입력에 포커스를 설정할 수 있습니다.
<button (click)="myInput.focus()">Click Me</button>
<input #myInput></input>
답변
부울이 변경된 후 실행을 수행하고 시간 초과 사용을 방지하려면 다음을 수행 할 수 있습니다.
import { ChangeDetectorRef } from '@angular/core';
constructor(private cd: ChangeDetectorRef) {}
showSearch(){
this.show = !this.show;
this.cd.detectChanges();
this.searchElement.nativeElement.focus();
}