如何手动将我的 mdbootstrap angular.js 表单中的输入标记为无效?
How can I manually mark an input in my mdbootstrap angular.js form as invalid?
使用我当前的代码,如果输入为空或不符合输入类型的格式(例如:电子邮件必须具有“@”和“.”格式),我可以使输入显示为无效。
我的下一步是确保密码和确认密码字段匹配。我已经创建了一个比较两者的函数,但是在使用 mdbootstrap 表单实现它时遇到了很多麻烦。
我一直在玩的功能:
mustMatch(controlName: string, matchingControlName: string) {
return (formGroup: FormGroup) => {
const control = formGroup.controls[controlName];
const matchingControl = formGroup.controls[matchingControlName];
if (matchingControl.errors && !matchingControl.errors.mustMatch) {
// var passwordInput = document.getElementById('password');
// passwordInput.classList.remove('ng-valid');
// passwordInput.classList.add('ng-invalid');
formGroup.controls['password'].setErrors({'incorrect': true});
return;
}
if (control.value !== matchingControl.value) {
matchingControl.setErrors({ mustMatch: true });
} else {
matchingControl.setErrors(null);
}
};
}
我需要使无效的元素:
<div class="col-xs-12">
<div class="form-outline">
<input formControlName="password" type="password" id="password" class="form-control pb-3" required/>
<label class="form-label" for="password">Password</label>
<div class="invalid-feedback">Please enter your password.</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-outline">
<input formControlName="confirmPassword" type="password" id="confirmPass" class="form-control pb-3" required/>
<label class="form-label" for="confirmPass">Confirm Password</label>
<div class="invalid-feedback">Please confirm your password.</div>
</div>
</div>
窗体的初始化:
ngOnInit(): void {
document.querySelectorAll('.form-outline').forEach((formOutline) => {
new mdb.Input(formOutline).init();
});
this.setupSignupForm();
const forms = document.querySelectorAll('.needs-validation');
Array.prototype.slice.call(forms).forEach((form) => {
form.addEventListener('submit', (event) => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
setupSignupForm(): void {
this.signupForm = this.formBuilder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['',
[
Validators.required,
Validators.email,
]],
confirmEmail: ['',
[
Validators.required,
Validators.email,
]],
joinCode: ['', Validators.required],
password: ['', Validators.required],
confirmPassword: ['',
[
Validators.required,
]]
}, {
validators: [this.mustMatch('password', 'confirmPassword'), this.mustMatch('email', 'confirmEmail')]
});
}
如果您能弄清楚如何做到这一点,请告诉我。在这个问题上我一直在用头撞墙!
Here is a picture of what I am dealing with:
我认为最好为每个 form-control
使用 validator
而不是整个 form-group
,因为:
form-group
验证器将检查表单中的任何更改,即使这些更改与目标 form-control
(s)(password
和 email
在你的情况下)。
- 您必须手动设置错误 (
setErrors
),并以相同的方式删除它们。
相反,您可以通过将验证器分配给 form-control
本身来实现它,如下所示:
setupSignupForm(): void {
this.signupForm = this.formBuilder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
confirmEmail: [
'',
[Validators.required, Validators.email, this.mustMatch('email')]
],
joinCode: ['', Validators.required],
password: ['', Validators.required],
confirmPassword: ['', [Validators.required, this.mustMatch('password')]]
});
}
mustMatch(matchingControlName: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!control.parent) return;
const matchingCtrlValue = control.parent.get(matchingControlName).value;
if (control.value !== matchingCtrlValue) {
return { mustMatch: true };
} else {
return null;
}
};
}
mdboostrat 验证可以将 :invalid 和 :valid 样式添加到父 .was-validated class。但是您也可以在您的输入中添加 class is-valid 或 is-invalid (而不是在表单中添加 was-validated)
所以我建议另一种方法:
1.-在您的代码中删除
/**Remove this lines**
const forms = document.querySelectorAll('.needs-validation');
Array.prototype.slice.call(forms).forEach((form) => {
form.addEventListener('submit', (event) => {
...
});
2.-在你的输入中使用
<input [ngClass]="'is-valid':form.get('password').invalid &&
form.get('password').touched;
'is-invalid':form.get('password').valid &&
form.get('password').touched">
好吧,在我们所有的输入中重复一遍,ngClass 有点“奇怪”。那么,为什么不使用为我们制定的指令呢?
想象一下这样的指令
@Directive({
selector: '.form-control'
})
export class MdClassDirective {
@HostBinding('class.is-valid') get valid() {
return (
(!this.form || this.form.classList.contains('submitted')) &&
this.control &&
this.control.touched &&
this.control.valid
);
}
@HostBinding('class.is-invalid') get invalid() {
return (
(!this.form || this.form.classList.contains('submitted')) &&
this.control &&
this.control.touched &&
this.control.invalid
);
}
form: any;
constructor(@Optional() private control: NgControl, el: ElementRef) {
//we need get the "html form"
this.form = el.nativeElement;
while (this.form.parentElement && !(this.form instanceof HTMLFormElement)) {
this.form = this.form.parentElement;
}
}
}
此指令将 class 有效或无效添加到您的输入中 class “form-control” if is touched and the “form” has as class提交。所以这项工作以 html 形式,例如-查看 [[=33=]]="已提交"-
<form [formGroup]="form" (submit)="submitted=true;submit()"
[class.submitted]="submitted">
<input class="form-control" formControlName="name" >
<button>submit</button>
</form>
不要忘记在提交的函数中将元素标记为输入
submit() {
this.form.markAllAsTouched();
}
这样就可以在Angular中正常使用customValidator了。
使用我当前的代码,如果输入为空或不符合输入类型的格式(例如:电子邮件必须具有“@”和“.”格式),我可以使输入显示为无效。
我的下一步是确保密码和确认密码字段匹配。我已经创建了一个比较两者的函数,但是在使用 mdbootstrap 表单实现它时遇到了很多麻烦。
我一直在玩的功能:
mustMatch(controlName: string, matchingControlName: string) {
return (formGroup: FormGroup) => {
const control = formGroup.controls[controlName];
const matchingControl = formGroup.controls[matchingControlName];
if (matchingControl.errors && !matchingControl.errors.mustMatch) {
// var passwordInput = document.getElementById('password');
// passwordInput.classList.remove('ng-valid');
// passwordInput.classList.add('ng-invalid');
formGroup.controls['password'].setErrors({'incorrect': true});
return;
}
if (control.value !== matchingControl.value) {
matchingControl.setErrors({ mustMatch: true });
} else {
matchingControl.setErrors(null);
}
};
}
我需要使无效的元素:
<div class="col-xs-12">
<div class="form-outline">
<input formControlName="password" type="password" id="password" class="form-control pb-3" required/>
<label class="form-label" for="password">Password</label>
<div class="invalid-feedback">Please enter your password.</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-outline">
<input formControlName="confirmPassword" type="password" id="confirmPass" class="form-control pb-3" required/>
<label class="form-label" for="confirmPass">Confirm Password</label>
<div class="invalid-feedback">Please confirm your password.</div>
</div>
</div>
窗体的初始化:
ngOnInit(): void {
document.querySelectorAll('.form-outline').forEach((formOutline) => {
new mdb.Input(formOutline).init();
});
this.setupSignupForm();
const forms = document.querySelectorAll('.needs-validation');
Array.prototype.slice.call(forms).forEach((form) => {
form.addEventListener('submit', (event) => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
setupSignupForm(): void {
this.signupForm = this.formBuilder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['',
[
Validators.required,
Validators.email,
]],
confirmEmail: ['',
[
Validators.required,
Validators.email,
]],
joinCode: ['', Validators.required],
password: ['', Validators.required],
confirmPassword: ['',
[
Validators.required,
]]
}, {
validators: [this.mustMatch('password', 'confirmPassword'), this.mustMatch('email', 'confirmEmail')]
});
}
如果您能弄清楚如何做到这一点,请告诉我。在这个问题上我一直在用头撞墙!
Here is a picture of what I am dealing with:
我认为最好为每个 form-control
使用 validator
而不是整个 form-group
,因为:
form-group
验证器将检查表单中的任何更改,即使这些更改与目标form-control
(s)(password
和email
在你的情况下)。- 您必须手动设置错误 (
setErrors
),并以相同的方式删除它们。
相反,您可以通过将验证器分配给 form-control
本身来实现它,如下所示:
setupSignupForm(): void {
this.signupForm = this.formBuilder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
confirmEmail: [
'',
[Validators.required, Validators.email, this.mustMatch('email')]
],
joinCode: ['', Validators.required],
password: ['', Validators.required],
confirmPassword: ['', [Validators.required, this.mustMatch('password')]]
});
}
mustMatch(matchingControlName: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!control.parent) return;
const matchingCtrlValue = control.parent.get(matchingControlName).value;
if (control.value !== matchingCtrlValue) {
return { mustMatch: true };
} else {
return null;
}
};
}
mdboostrat 验证可以将 :invalid 和 :valid 样式添加到父 .was-validated class。但是您也可以在您的输入中添加 class is-valid 或 is-invalid (而不是在表单中添加 was-validated)
所以我建议另一种方法:
1.-在您的代码中删除
/**Remove this lines**
const forms = document.querySelectorAll('.needs-validation');
Array.prototype.slice.call(forms).forEach((form) => {
form.addEventListener('submit', (event) => {
...
});
2.-在你的输入中使用
<input [ngClass]="'is-valid':form.get('password').invalid &&
form.get('password').touched;
'is-invalid':form.get('password').valid &&
form.get('password').touched">
好吧,在我们所有的输入中重复一遍,ngClass 有点“奇怪”。那么,为什么不使用为我们制定的指令呢?
想象一下这样的指令
@Directive({
selector: '.form-control'
})
export class MdClassDirective {
@HostBinding('class.is-valid') get valid() {
return (
(!this.form || this.form.classList.contains('submitted')) &&
this.control &&
this.control.touched &&
this.control.valid
);
}
@HostBinding('class.is-invalid') get invalid() {
return (
(!this.form || this.form.classList.contains('submitted')) &&
this.control &&
this.control.touched &&
this.control.invalid
);
}
form: any;
constructor(@Optional() private control: NgControl, el: ElementRef) {
//we need get the "html form"
this.form = el.nativeElement;
while (this.form.parentElement && !(this.form instanceof HTMLFormElement)) {
this.form = this.form.parentElement;
}
}
}
此指令将 class 有效或无效添加到您的输入中 class “form-control” if is touched and the “form” has as class提交。所以这项工作以 html 形式,例如-查看 [[=33=]]="已提交"-
<form [formGroup]="form" (submit)="submitted=true;submit()"
[class.submitted]="submitted">
<input class="form-control" formControlName="name" >
<button>submit</button>
</form>
不要忘记在提交的函数中将元素标记为输入
submit() {
this.form.markAllAsTouched();
}
这样就可以在Angular中正常使用customValidator了。