programing

초점설정에 합니다.초점설정에 합니다.초점설정에 합니다.

lastcode 2023. 5. 17. 23:13
반응형

초점설정에 합니다.

저는 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();
  }

검색 상자가 포커스로 설정되지 않았습니다.

내가 어떻게 그럴 수 있을까?

2022년 편집:
아래의 @Cichy의 대답으로 더 현대적인 방법을 읽으십시오.


다음과 같이 검색 방법 표시 수정

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 조각 내부에서 자동 포커스 특성을 확인한 다음 JavaScript를 통해 다시 적용하거나 포커스를 지정하여 해결할 수 있습니다.

다음은 글로벌 리스너의 예로, 스파 애플리케이션에 한 번만 배치하면 동일한 조각이 재사용되는 횟수에 관계없이 자동 포커스가 작동합니다.

(new MutationObserver(function (mutations, observer) {
    for (let i = 0; i < mutations.length; i++) {
        const m = mutations[i];
        if (m.type == 'childList') {
            for (let k = 0; k < m.addedNodes.length; k++) {
                const autofocuses = m.addedNodes[k].querySelectorAll("[autofocus]"); //Note: this ignores the fragment's root element
                console.log(autofocuses);
                if (autofocuses.length) {
                    const a = autofocuses[autofocuses.length - 1]; // focus last autofocus element
                    a.focus();
                    a.select();
                }
            }
        }
    }
})).observe(document.body, { attributes: false, childList: true, subtree: true });

이 지시어는 표시되는 즉시 요소의 텍스트에 초점을 맞추고 선택합니다.일부 경우에는 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>

구성 요소의 html:

<input [cdkTrapFocusAutoCapture]="show" [cdkTrapFocus]="show">

구성 요소 컨트롤러:

showSearch() {
  this.show = !this.show;    
}

..A11yModule을 @angular/cdk/a11y에서 가져오는 것도 잊지 마십시오.

import { A11yModule } from '@angular/cdk/a11y'

저는 이 문제를 고려할 것입니다(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 없이 iAngular 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();
  }
}

설명:자, 이것이 작동하는 이유는 변화 감지 때문입니다.setTimeout이 작동하는 이유와 동일하지만, Angular에서 setTimeout을 실행하면 Zone.js를 바이패스하여 모든 검사를 다시 실행하고 setTimeout이 완료되면 모든 변경이 완료되므로 작동합니다.올바른 라이프사이클 후크(AfterContentChecked)를 사용하면 동일한 결과를 얻을 수 있지만 추가 사이클이 실행되지 않는다는 장점이 있습니다.이 기능은 모든 변경사항을 확인하고 통과하면 실행되며, 내용 후 후크 이후에 실행됩니다.Init 및 DoCheck.여기서 제가 틀렸다면 고쳐주세요.

https://angular.io/guide/lifecycle-hooks 에서 라이프사이클 및 변경 감지 기능을 하나 더 제공합니다.

업데이트: A11y 패키지인 Angular Material CDK를 사용하는 경우 훨씬 더 좋은 방법을 찾았습니다.먼저 입력 필드가 있는 구성 요소를 선언하는 모듈에서 A11yModule을 가져옵니다.그런 다음 cdkTrapFocuscdkTrapFocus를 사용합니다.AutoCapture 명령어는 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();
}

저도 같은 시나리오를 쓰고 있습니다. 이것은 저에게 효과가 있었지만, 저는 당신이 가지고 있는 "숨기기/보기" 기능을 가지고 있지 않습니다.따라서 필드를 항상 볼 수 있을 때 먼저 포커스가 있는지 확인한 다음, 가시성을 변경할 때 작동하지 않는 이유를 해결하려고 시도할 수 있습니다(아마도 그렇기 때문에 수면 또는 약속을 적용해야 할 것입니다)

포커스를 설정하려면 다음과 같이 변경해야 합니다.

HTML 매트 입력은 다음과 같아야 합니다.

<input #yourControlName matInput>

TS 클래스에서 변수 섹션에서 이와 같은 참조(

export class blabla...
    @ViewChild("yourControlName") yourControl : ElementRef;

버튼을 누르면 됩니다. 전화하세요.

  showSearch(){
       ///blabla... then finally:
       this.yourControl.nativeElement.focus();
}

그리고 이것이 마지막입니다.제가 찾은 이 게시물에서 이 솔루션을 확인하실 수 있습니다. 덕분에 --> https://codeburst.io/focusing-on-form-elements-the-angular-way-e9a78725c04f

DOM성있다라는 DOM .cdkFocusInitial입력에 효과가 있습니다.자세한 내용은 여기에서 확인할 수 있습니다. https://material.angular.io/cdk/a11y/overview

각도 템플릿만 사용

<input type="text" #searchText>

<span (click)="searchText.focus()">clear</span>

할 때는 오대이/화를상사때를 .cdkFocusInitial에 내에cdkTrapFocus그리고.cdkTrapFocusAutoCapture.

CDK 지역:

CdkTrapFocus 디렉티브와 함께 cdkFocusInitial을 사용하는 경우 cdkTrapFocus를 활성화하지 않으면 아무 일도 일어나지 않습니다.AutoCapture 옵션도 있습니다.이는 CdkTrapFocus가 기본적으로 초기화에 대한 포커스를 캡처하지 않기 때문입니다.

오버레이/대화 상자 구성 요소:

<div cdkTrapFocus cdkTrapFocusAutoCapture>
  <input cdkFocusInitial>
</div>

@john-white 제로셋 타임아웃으로 마법이 작동하는 이유는

this.searchElement.nativeElement.focus();

브라우저 callStack의 끝으로 전송되므로 마지막/나중에 실행됩니다. 이것은 그것을 작동시키는 아주 좋은 방법이 아니며 아마도 코드에 개선될 수 있는 다른 논리가 있다는 것을 의미합니다.

저는 블러 기능을 사용한 후에야 작동했습니다.

그것을 깨끗하게 유지하기 위해 나는 그것에 대한 지시를 내렸습니다.

import { Directive, ElementRef } from '@angular/core';
import { IonInput } from '@ionic/angular';

@Directive({
  selector: '[appAutofocus]'
})
export class AutofocusDirective {
  constructor(private el: ElementRef) {
  }
    
  async ngOnInit() {
    const input = this.el.nativeElement as IonInput;

    await input.setBlur();
    await input.setFocus();
  }
}

이것을 하는 것도 더 쉬운 방법입니다.

let elementReference = document.querySelector('<your css, #id selector>');
    if (elementReference instanceof HTMLElement) {
        elementReference.focus();
    }

언급URL : https://stackoverflow.com/questions/50006888/set-focus-on-input-element

반응형