gpt4 book ai didi

javascript - Angular 自定义焦点指令。聚焦表单的第一个无效输入

转载 作者:行者123 更新时间:2023-12-01 00:56:39 25 4
gpt4 key购买 nike

我创建了一个指令,用于在输入无效时将其聚焦

import { Directive, Input, Renderer2, ElementRef, OnChanges } from '@angular/core';

@Directive({
// tslint:disable-next-line:directive-selector
selector: '[focusOnError]'
})
export class HighlightDirective implements OnChanges {
@Input() submitted: string;

constructor(private renderer: Renderer2, private el: ElementRef) { }

ngOnChanges(): void {
const el = this.renderer.selectRootElement(this.el.nativeElement);
if (this.submitted && el && el.classList.contains('ng-invalid') && el.focus) {
setTimeout(() => el.focus());
}
}

}

我确实有一个带有两个输入的响应式(Reactive)表单,并且我已将指令应用于两个输入

<form>
...
<input type="text" id="familyName" focusOnError />
...
<input type="text" id="appointmentCode" focusOnError />
...
</form>

提交表单后,它工作正常,但我正在努力实现以下目标:

预期结果:- 提交表单后,如果两个输入都无效,则只应关注第一个输入。

当前结果:- 提交表单后,如果两个输入都无效,则第二个输入将获得焦点。

我不知道如何指定“仅在它是第一个子项时才执行此操作”,我尝试过使用指令的选择器,但没有成功。

有什么想法吗?

提前非常感谢。

最佳答案

为了控制表单的输入,我认为更好的解决方案是使用 ViewChildren 来获取所有元素。因此,我们可以循环遍历这些元素并聚焦第一个元素。

所以,我们可以有一个辅助的简单指令:

@Directive({
selector: '[focusOnError]'
})
export class FocusOnErrorDirective {

public get invalid()
{
return this.control?this.control.invalid:false;
}
public focus()
{
this.el.nativeElement.focus()
}
constructor(@Optional() private control: NgControl, private el: ElementRef) { }
}

而且,在我们的组件中,我们有一些类似

@ViewChildren(FocusOnErrorDirective) fields:QueryList<FocusOnErrorDirective>
check() {
const fields=this.fields.toArray();
for (let field of fields)
{
if (field.invalid)
{
field.focus();
break;
}
}
}

您可以在 stackblitz 中看到实际情况

更新总是可以改进的:

为什么不创建一个应用于表单的指令?

@Directive({
selector: '[focusOnError]'
})
export class FocusOnErrorDirective {

@ContentChildren(NgControl) fields: QueryList<NgControl>

@HostListener('submit')
check() {
const fields = this.fields.toArray();
for (let field of fields) {
if (field.invalid) {
(field.valueAccessor as any)._elementRef.nativeElement.focus();
break;
}
}
}

所以,我们的 .html 就像

<form [formGroup]="myForm" focusOnError>
<input type="text" formControlName="familyName" />
<input type="text" formControlName="appointmentCode" />
<button >click</button>
</form>

请参阅stackblitz

更重要的是,如果我们使用作为选择器表单

@Directive({
selector: 'form'
})

甚至我们可以删除表单中的 focusOnError

<form [formGroup]="myForm" (submit)="submit(myForm)">
..
</form>

更新2 formGroup 与 formGroup 的问题。 已解决

NgControl 只考虑具有 [(ngModel)]、formControlName 和 [formControl] 的控件,所以。如果我们可以使用像

这样的形式
myForm = new FormGroup({
familyName: new FormControl('', Validators.required),
appointmentCode: new FormControl('', Validators.required),
group: new FormGroup({
subfamilyName: new FormControl('', Validators.required),
subappointmentCode: new FormControl('', Validators.required)
})
})

我们可以使用如下形式:

<form [formGroup]="myForm"  focusOnError (submit)="submit(myForm)">
<input type="text" formControlName="familyName" />
<input type="text" formControlName="appointmentCode" />
<div >
<input type="text" [formControl]="group.get('subfamilyName')" />
<input type="text" [formControl]="group.get('subappointmentCode')" />
</div>
<button >click</button>
</form>

.ts 中我们有

get group()
{
return this.myForm.get('group')
}

更新 3 使用 Angular 8,您可以获得子级的后代,因此只需编写

 @ContentChildren(NgControl,{descendants:true}) fields: QueryList<NgControl>

关于javascript - Angular 自定义焦点指令。聚焦表单的第一个无效输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56525783/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com