Angular2+ 자동 포커스 입력 요소
입력 요소를 자동 포커스하려면 어떻게 해야 합니까?이 질문과 비슷하지만 AngularDart에서는 그렇지 않습니다.이와 같은 것:
<input type="text" [(ngModel)]="title" [focus] />
//or
<input type="text" [(ngModel)]="title" autofocus />
Angular2는 이 기능을 지원하는 빌드가 있습니까?
가장 가까운 질문은 이것입니다. 하지만 "입력 상자 목록"이 없기 때문에 더 짧고 쉬운 해결책은 없을까요?제공된 링크*ngFor="#input of inputs"
사용되고 있지만 제어 템플릿에 입력된 것은 하나뿐입니다.
현재 코드는 다음과 같습니다.
import { Directive, ElementRef, Input } from "@angular/core";
@Directive({
selector: "[autofocus]"
})
export class AutofocusDirective
{
private focus = true;
constructor(private el: ElementRef)
{
}
ngOnInit()
{
if (this.focus)
{
//Otherwise Angular throws error: Expression has changed after it was checked.
window.setTimeout(() =>
{
this.el.nativeElement.focus(); //For SSR (server side rendering) this is not safe. Use: https://github.com/angular/angular/issues/15008#issuecomment-285141070)
});
}
}
@Input() set autofocus(condition: boolean)
{
this.focus = condition !== false;
}
}
사용 사례:
[autofocus] //will focus
[autofocus]="true" //will focus
[autofocus]="false" //will not focus
오래된 코드(예전의 답변, 만일의 경우):
저는 결국 이 코드로 끝났습니다.
import {Directive, ElementRef, Renderer} from '@angular/core';
@Directive({
selector: '[autofocus]'
})
export class Autofocus
{
constructor(private el: ElementRef, private renderer: Renderer)
{
}
ngOnInit()
{
}
ngAfterViewInit()
{
this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []);
}
}
에 코드를 ,ngOnViewInit
작동하지 않습니다.요소에 초점을 직접 맞추는 것은 권장되지 않으므로 코드에서도 모범 사례를 사용합니다.
편집됨(조건부 자동 포커스):
며칠 전에는 첫 번째 자동 포커스 요소를 숨기고 다른 요소에 포커스를 맞추고 싶지만 처음이 보이지 않을 때만 해당하므로 조건부 자동 포커스가 필요했고 다음 코드는 다음과 같습니다.
import { Directive, ElementRef, Renderer, Input } from '@angular/core';
@Directive({
selector: '[autofocus]'
})
export class AutofocusDirective
{
private _autofocus;
constructor(private el: ElementRef, private renderer: Renderer)
{
}
ngOnInit()
{
}
ngAfterViewInit()
{
if (this._autofocus || typeof this._autofocus === "undefined")
this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []);
}
@Input() set autofocus(condition: boolean)
{
this._autofocus = condition != false;
}
}
편집됨2:
Renderer.invokeElementMethod는 더 이상 사용되지 않으며 새 Renderer2는 이를 지원하지 않습니다.따라서 기본 포커스로 돌아갑니다(예: DOM - SSR 외부에서는 작동하지 않음!).
import { Directive, ElementRef, Input } from '@angular/core';
@Directive({
selector: '[autofocus]'
})
export class AutofocusDirective
{
private _autofocus;
constructor(private el: ElementRef)
{
}
ngOnInit()
{
if (this._autofocus || typeof this._autofocus === "undefined")
this.el.nativeElement.focus(); //For SSR (server side rendering) this is not safe. Use: https://github.com/angular/angular/issues/15008#issuecomment-285141070)
}
@Input() set autofocus(condition: boolean)
{
this._autofocus = condition != false;
}
}
사용 사례:
[autofocus] //will focus
[autofocus]="true" //will focus
[autofocus]="false" //will not focus
autofocus
최소한 페이지 초기화에 사용할 수 있는 기본 HTML 기능입니다.그러나 많은 각도의 시나리오에서 작동하지 않습니다. 특히,*ngIf
.
원하는 동작을 얻기 위해 정말 간단한 사용자 지정 지침을 만들 수 있습니다.
import { Directive, OnInit, ElementRef } from '@angular/core';
@Directive({
selector: '[myAutofocus]'
})
export class AutofocusDirective implements OnInit {
constructor(private elementRef: ElementRef) { };
ngOnInit(): void {
this.elementRef.nativeElement.focus();
}
}
위 지침은 저의 사용 사례에 적용됩니다.
사용방법
<input *ngIf="someCondition" myAutofocus />
편집: 포커스를 부르기에는 너무 이른 사용 사례가 있는 것 같습니다.OnInit
라이프 사이클 방법이 경우 다음으로 변경합니다.OnAfterViewInit
대신.
변수를 할 수 .#myInput
:
<input type="text" [(ngModel)]="title" #myInput />
요소가 구성요도합니다록되를 구현하도록 .AfterViewInit
을 를사하 요의기잡습준으로 .ViewChild
을 맞춥니다.ngAfterViewInit
잠금 해제:
export class MyComponent implements AfterViewInit {
@ViewChild("myInput") private _inputElement: ElementRef;
[...]
ngAfterViewInit(): void {
this._inputElement.nativeElement.focus();
}
}
<input type="text" [(ngModel)]="title" #myInput />
{{ myInput.focus() }}
템플릿 내부 입력 직후 {{myInput.focus()}}을(를) 추가하기만 하면 됩니다.
다음 지침은 Angular 4.0.1을 사용하는 경우에 사용할 수 있습니다.
import {Directive, ElementRef, AfterViewInit} from '@angular/core';
@Directive({
selector: '[myAutofocus]'
})
export class MyAutofocusDirective implements AfterViewInit {
constructor(private el: ElementRef)
{
}
ngAfterViewInit()
{
this.el.nativeElement.focus();
}
}
다음과 같이 사용합니다.
<md-input-container>
<input mdInput placeholder="Item Id" formControlName="itemId" name="itemId" myAutofocus>
</md-input-container>
OnInit 라이프사이클 이벤트를 사용하는 옵션은 저에게 적용되지 않았습니다.저는 또한 다른 답변에서 렌더러를 사용해 보았지만 저에게는 통하지 않았습니다.
true/false 기능이 필요하지 않지만 항상 자동 포커스를 설정하려면 Makla의 솔루션을 보다 짧게 구현할 수 있습니다.
autofocus.dll.ts:
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
@Directive({
selector: '[autofocus]'
})
export class AutofocusDirective implements AfterViewInit {
constructor(private el: ElementRef) {
}
ngAfterViewInit() {
// Otherwise Angular throws error: Expression has changed after it was checked.
window.setTimeout(() => {
this.el.nativeElement.focus();
});
}
}
사용 사례:
<input autofocus> //will focus
AfterViewOnInit 대신 Init은 내용이 채워질 경우 입력 필드의 내용 뒤에 커서를 놓습니다.
모듈에서 자동 포커스 지시문을 선언하고 내보내는 것을 기억하십시오!
스마트 자동 포커스(다이나믹 포커스) 지침
Angular 오토포커스 지시사항에 대한 제 견해는 이렇습니다.
다음 지시어는 부울 값을 입력으로 수락하고 요소가 동적으로 초점을 맞출 수 있도록 평가된 부울 식을 기반으로 요소에 초점을 맞춥니다.
또한 지침을 적용할 수 있습니다.input
/button
/select
/a
요소를 직접 또는 상위 요소에도 적용할 수 있습니다.DOM에서 자동으로 초점을 맞출 첫 번째 적합한 요소를 검색합니다.
코드
import { AfterViewInit, Directive, ElementRef, Input, NgModule } from '@angular/core';
const focusableElements = [
'input',
'select',
'button',
'a',
];
@Directive({
selector: '[autofocus]',
})
export class AutofocusDirective implements AfterViewInit {
@Input()
public set autofocus(shouldFocus: boolean) {
this.shouldFocus = shouldFocus;
this.checkFocus();
}
private shouldFocus = true;
constructor(
private readonly elementRef: ElementRef
) {
}
public ngAfterViewInit() {
this.checkFocus();
}
private checkFocus() {
if (!this.shouldFocus) {
return;
}
const hostElement = (
<HTMLElement>
this.elementRef.nativeElement
);
if (!hostElement) {
return;
}
if (focusableElements.includes(
hostElement.tagName.toLowerCase())
) {
hostElement.focus?.();
} else if (hostElement?.querySelector) {
for (const tagName of focusableElements) {
const childElement = (
<HTMLInputElement>
hostElement.querySelector(tagName)
);
if (childElement) {
childElement?.focus?.();
break;
}
}
}
}
}
@NgModule({
declarations: [
AutofocusDirective,
],
exports: [
AutofocusDirective,
],
})
export class AutofocusModule {
}
사용 예
<!-- These are equivalent: -->
<input type="text" autofocus>
<input type="text" [autofocus]>
<input type="text" [autofocus]="true">
<!-- Conditional (dynamic) focusing: -->
<input type="text" [autofocus]="shouldBeFocused">
<input type="text" name="username" [autofocus]="focusedField === 'username'">
<!-- Using parent element: -->
<fieldset autofocus>
<label>
Username:
<input type="text">
</label>
</fieldset>
알려드립니다
이 코드는 최신 브라우저 환경에서만 완전히 작동하지만 다른 환경에서는 사용할 수 없습니다(예쁜 성능 저하).
IE11부터는 다른 모든 최신 브라우저와 마찬가지로 입력에 대한 네이티브 HTML 자동 포커스 속성도 Angular:
<input autofocus>
<input type="text" [(ngModel)]="title" autofocus>
갱신하다
아래 @adrug의 논평에서 언급한 바와 같이, 이 접근법은 함정이 있습니다.페이지가 로드될 때 한 번만 작동합니다.
Netanel Basal의 기사에서 설명한 것처럼, 더 나은 방법은 Angular Directive로 구현하는 것입니다.이미 다른 답변에서 제안한 바와 같이.
간단하지만 효과적인 이 기능을 사용해 보십시오.:
function addFocusInput() {
document.getElementById('text-focus').focus();
}
addFocusInput();
<input id="text-focus" type="text" placeholder=""/>
이 게시물이 오래된 게시물이라는 것을 알지만 새로운 답을 찾는 다른 사람들을 위한 것입니다.각진 재료 대화 상자를 사용하고 있었는데 입력이 아닌 닫기 버튼을 자동으로 선택하고 있었습니다.
사용.cdk-focus-start
(CDK의 일부)는 추가 코드 없이 이 문제를 해결합니다.
내 솔루션:
<input type="text" id="searchInput">
// put focus on element with id 'searchInput', try every 100ms and retry 30 times
this.focus('searchInput',30,100);
focus( idElement:string, maxNbRetries:number, intervalMs:number){
let nbRetries = 0;
let elt = null;
const stop$ = new Subject<boolean>();
const source = interval(intervalMs);
const source$ = source.pipe(
tap(item=>{
elt = document.getElementById(idElement);
nbRetries++;
if(nbRetries>maxNbRetries){
stop$.next(true);
console.log(`unable to put the focus on the element !`)
}
}),
filter(item=>elt !=null),
map(item=>{
elt.focus();
stop$.next(true);
}),
takeUntil(stop$)
).subscribe();
}
포커스는 각 라이프사이클에서 잘 작동하지 않습니다.필드에 강제로 적용하기 위해 모든 'intervalMs'를 방출하는 관측치를 실행합니다.요소가 렌더링된 경우 ID로 찾을 수 있습니다.그런 다음 포커스를 설정할 수 있습니다.nbRetries > maxNbRetries 또는 요소 ID가 발견되면 takeUntil 연산자를 사용하여 관찰 가능한 항목을 중지합니다.
myReactiveForm!: FormGroup;
constructor(public el: ElementRef) { }
onSubmit(myReactiveForm: any) {
this.autoFocusOnError(myReactiveForm, this.el);
}
자동 포커스에 이 기능을 사용합니다.
autoFocusOnError(form: any, el:any) {
form.markAllAsTouched();
for (const key of Object?.keys(form?.controls)) {
if (form?.controls[key].invalid) {
let rootElement = el.nativeElement;
let invalidControl = rootElement.querySelector('[formcontrolname="' + key + '"]') ||
rootElement.querySelector('[name="' + key + '"]');
if (invalidControl?.tagName == "NG-SELECT") {
invalidControl = invalidControl.querySelector("div.ng-select-container input");
} else if (invalidControl?.tagName == "NG-MULTISELECT-DROPDOWN") {
invalidControl = invalidControl.querySelector("div.multiselect-dropdown");
}
invalidControl?.focus();
return false;
}
}
return true;
}
언급URL : https://stackoverflow.com/questions/41873893/angular2-autofocus-input-element
'programing' 카테고리의 다른 글
MySQL/MariaDB가 저장 시 자동으로 값을 변경할 수 있는 방법 (0) | 2023.08.15 |
---|---|
요소의 중심을 수평 및 수직으로 맞추는 방법 (0) | 2023.08.15 |
HTML로 애니메이션 로드를 활성화하고 있습니다.양식 제출 시작 (0) | 2023.08.15 |
내용 편집 가능한 div의 자리 표시자 (0) | 2023.08.15 |
문서 흐름에서 공간을 차지하지 않고 요소를 상대적으로 배치합니다. (0) | 2023.08.15 |