Javascript 角度6反应形式:如何设置第一个无效输入的焦点
在我的Angular 6应用程序下,我正在使用反应式表单 我的目的是在提交时,我想在出现错误时将焦点设置在第一个无效输入上 我的表单如下所示: 我尝试了自动对焦指令,但没有成功Javascript 角度6反应形式:如何设置第一个无效输入的焦点,javascript,angular,html,rxjs,angular-reactive-forms,Javascript,Angular,Html,Rxjs,Angular Reactive Forms,在我的Angular 6应用程序下,我正在使用反应式表单 我的目的是在提交时,我想在出现错误时将焦点设置在第一个无效输入上 我的表单如下所示: 我尝试了自动对焦指令,但没有成功 建议?我的答案来源于这里的。我使用他回答中的逻辑,通过使用FormControl获取特定FormControl的nativeElement 这就是这样做的逻辑: const originFormControlNameNgOnChanges = FormControlName.prototype.ngOnChanges;
建议?我的答案来源于这里的。我使用他回答中的逻辑,通过使用
FormControl
获取特定FormControl
的nativeElement
这就是这样做的逻辑:
const originFormControlNameNgOnChanges = FormControlName.prototype.ngOnChanges;
FormControlName.prototype.ngOnChanges = function () {
const result = originFormControlNameNgOnChanges.apply(this, arguments);
this.control.nativeElement = this.valueAccessor._elementRef.nativeElement;
return result;
};
现在,表单的errors字段将为null,即使它的字段无效。因此,为了得到第一个无效的字段,我们必须遍历所有字段并检查每个字段的有效性。我可以在onSubmitForm()
方法中编写此逻辑。大概是这样的:
onSubmitForm() {
const fieldsToCheck = [
'codeBasicat',
'libellePef',
'nomApplication'
];
for (let i = 0; i < fieldsToCheck.length; i++) {
const fieldName = fieldsToCheck[i];
if (this.addItemfForm.get(fieldName).invalid) {
( < any > this.addItemfForm.get(fieldName)).nativeElement.focus();
break;
}
}
}
<form [formGroup]="userForm" (submit)="saveData()" appFocus >
...
</form>
onSubmitForm(){
常量字段STOCHECK=[
“codeBasicat”,
“诽谤”,
“无应用程序”
];
for(设i=0;ithis.additemform.get(fieldName)).nativeElement.focus();
打破
}
}
}
我故意使用for
而不是Array.forEach
,因为我想打破循环
希望这能帮到你
这是给你的裁判的一封信
我是用指令做的。因此,我的表单如下所示:
onSubmitForm() {
const fieldsToCheck = [
'codeBasicat',
'libellePef',
'nomApplication'
];
for (let i = 0; i < fieldsToCheck.length; i++) {
const fieldName = fieldsToCheck[i];
if (this.addItemfForm.get(fieldName).invalid) {
( < any > this.addItemfForm.get(fieldName)).nativeElement.focus();
break;
}
}
}
<form [formGroup]="userForm" (submit)="saveData()" appFocus >
...
</form>
...
以及指令本身的代码:
import { Directive, HostListener, Input, ElementRef } from '@angular/core';
import { NgForm } from '@angular/forms';
@Directive({
selector: '[appFocus]'
})
export class FocusDirective {
constructor(private el: ElementRef) { }
@Input() formGroup: NgForm;
@HostListener('submit', ['$event'])
public onSubmit(event): void {
if ('INVALID' === this.formGroup.status) {
event.preventDefault();
const formGroupInvalid = this.el.nativeElement.querySelectorAll('.ng-invalid');
(<HTMLInputElement>formGroupInvalid[0]).focus();
}
}
}
import{Directive,HostListener,Input,ElementRef}来自“@angular/core”;
从'@angular/forms'导入{NgForm};
@指示({
选择器:“[appFocus]”
})
导出类FocusDirective{
构造函数(私有el:ElementRef){}
@Input()formGroup:NgForm;
@HostListener('提交',['$event']))
公开提交(事件):无效{
if('INVALID'==this.formGroup.status){
event.preventDefault();
const formGroupInvalid=this.el.nativeElement.querySelectorAll('.ng invalid');
(formGroupInvalid[0]).focus();
}
}
}
然而,这个解决方案是不完整的,因为有很多角落的情况,必须加以考虑。例如,如果第一个元素是单选按钮组,该怎么办。调度焦点事件将自动标记该字段。第二,不是所有angular ads ng invalid的元素都将成为输入。此选项对我不起作用,但我通过如下更改代码来修复它:
@Directive({
selector: '[appErrorFocusin]'
})
export class ErrorFocusinDirective {
selectorToFocus : String = 'textArea,mat-select,select,input,button';
constructor(private el: ElementRef,
@Inject(DOCUMENT) private document: Document) { }
@Input() formGroup: NgForm;
@HostListener('submit', ['$event'])
public onSubmit(event): void {
if ('INVALID' === this.formGroup.status) {
event.preventDefault();
const formGroupInvalid = this.el.nativeElement.querySelectorAll('.ng- invalid,:not(.mat-badge-hidden).mat-badge');
let elementToOffset = this.getElementToOffset(formGroupInvalid[0]);
this.document.documentElement.scrollTop = elementToOffset.offsetTop;
this.setFocusOnError(elementToOffset);
}
}
getElementToOffset(element : any){
let defaultElement = element;
while (!(element.parentElement instanceof HTMLFormElement)){
if (element.parentElement){
element = element.parentElement;
}else{
return defaultElement;
}
}
return element;
}
setFocusOnError(elementToOffset : any){
let listaElementos = elementToOffset.querySelectorAll(this.selectorToFocus);
if (listaElementos.length>0){
listaElementos[0].focus();
}
}
}
试试这个:
import { Directive, HostListener, ElementRef} from '@angular/core';
@Directive({
selector: '[focusFirstInvalidField]'
})
export class FocusFirstInvalidFieldDirective {
constructor(private el: ElementRef) { }
@HostListener('submit')
onFormSubmit() {
const invalidElements = this.el.nativeElement.querySelectorAll('.ng-invalid');
if (invalidElements.length > 0) {
console.log(invalidElements[0]);
invalidElements[0].focus();
}
}
}
请记住进行调试,看看元素0是否不是我遇到的您自己的表单,所以请正确查看它作为第一个字段报告的字段,并纠正位置。我们只需在表单的submit()中编写此代码,就可以将焦点设置在第一个无效输入上
if(this.form.invalid)
{
// Got focus to the error field
let invalidFields = [].slice.call(document.getElementsByClassName('ng-invalid'));
invalidFields[1].focus();
}
在提交时使用以下代码
for (const key of Object.keys(this.addressForm.controls)) {
if (this.addressForm.controls[key].invalid) {
const invalidControl = this.el.nativeElement.querySelector('[formcontrolname="' + key + '"]');
invalidControl.focus();
break;
}
}
此.addressForm将成为您的FormGroup
这里甚至不需要指令。我需要动态获取第一个出错输入的引用,并将焦点设置为it@firasKoubaa,我已经更新了我的答案。请检查一下这对你是否有效。我还添加了一个工作示例StackBlitz,您可能想看看。希望这会有帮助。@SiddAjmera您可以用来中断:)不过,我想查找DOM顺序中的第一个无效字段…querySelectorAll()返回一个NodeListOf,元素类型没有焦点()method@TheCodeFox对我来说,它起作用了,请检查您使用的是哪个版本,哪个是这个的类型。el?添加“private el:ElementRef”对于你的构造器(ElementRef格式'@angular/core'),它对我有效,但只对输入字段有效,对下拉字段无效。