FormBuilder 组已弃用
FormBuilder group is deprecated
我将我的项目迁移到 angular 11,我注意到我添加的全局验证使 FormBuilder.group
已弃用并显示以下消息:
group is deprecated: This api is not typesafe and can result in issues with Closure Compiler renaming.
Use the `FormBuilder#group` overload with `AbstractControlOptions` instead.
所以这已被弃用:
ingredientForm = this.fb.group({
ingredientType: ['', Validators.required],
ingredientFlavor: [''],
isMultiFlavor: [''],
ingredientBrand: [''],
ingredientName: [''],
imageFile: ['']
}, {validators: [ValidateThirdNumber.validate]});
没有 validators
选项就不是。
我的 ValidateThirdNumber
验证者:
class ValidateThirdNumber {
static validate(control: AbstractControl): void {
if (control) {
const isMultiFlavor = control.get('isMultiFlavor')?.value;
const ingredientFlavor = control.get('ingredientFlavor')?.value;
const ingredientBrand = control.get('ingredientBrand')?.value;
const ingredientName = control.get('ingredientName')?.value;
if (isMultiFlavor && ingredientFlavor.trim().length === 0) {
control.get('ingredientFlavor')?.setErrors({required_if: true});
} else {
control.get('ingredientFlavor')?.setErrors(null);
}
if (!ingredientFlavor && !ingredientBrand && !ingredientName) {
control.get('ingredientName')?.setErrors({required_at_least: true});
control.get('ingredientFlavor')?.setErrors({required_at_least: true});
control.get('ingredientBrand')?.setErrors({required_at_least: true});
} else {
control.get('ingredientName')?.setErrors(null);
control.get('ingredientFlavor')?.setErrors(null);
control.get('ingredientBrand')?.setErrors(null);
}
if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) {
control.get('ingredientName')?.setErrors({not_the_same: true});
control.get('ingredientBrand')?.setErrors({not_the_same: true});
}
}
}
}
如何使用 AbstractControlOptions 重载它?
问题描述
从 documentation 我们看到两个不同的行与 group()
函数
group(controlsConfig: { [key: string]: any; }, options?: AbstractControlOptions): FormGroup
AND
group(controlsConfig: { [key: string]: any; }, options: { [key: string]: any; }): FormGroup
第二个定义已弃用
这几行的区别是options?: AbstractControlOptions
和options: { [key: string]: any; }
要理解 angular 抛出此错误的原因,我们现在将考虑 AbstractControlOptions
interface AbstractControlOptions {
validators?: ValidatorFn | ValidatorFn[] | null
asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null
updateOn?: 'change' | 'blur' | 'submit'
}
我们继续分解问题,注意到这个结构和你的结构之间的区别是ValidatorFn[]
interface ValidatorFn {
(control: AbstractControl): ValidationErrors | null
}
总的来说,在您的情况下会引发错误,因为您的 Validator
函数应该控制 return ValidationErrors | null
。在行 validate(control: AbstractControl): void
中,您的代码实际上 returns void
但预期 return a ValidationError | null
解决方案
从问题描述来看,解决方法是简单修改ValidatorFn
确保您的 ValidatorFn
return 是 ValidationError
或者如果没有错误 return 是 null
来自 ValidationErrors defination
type ValidationErrors = {
[key: string]: any;
};
您将需要 return 键值对对象,例如 {required_if: true}
我们可以按预期添加 return 语句来更改您的代码
class ValidateThirdNumber {
static validate(control: AbstractControl): ValidationErrors | null {
if (control) {
const isMultiFlavor = control.get('isMultiFlavor')?.value;
const ingredientFlavor = control.get('ingredientFlavor')?.value;
const ingredientBrand = control.get('ingredientBrand')?.value;
const ingredientName = control.get('ingredientName')?.value;
if (isMultiFlavor && ingredientFlavor.trim().length === 0) {
control.get('ingredientFlavor')?.setErrors({required_if: true});
return ({required_if: true});
} else {
control.get('ingredientFlavor')?.setErrors(null);
}
if (!ingredientFlavor && !ingredientBrand && !ingredientName) {
control.get('ingredientName')?.setErrors({required_at_least: true});
control.get('ingredientFlavor')?.setErrors({required_at_least: true});
control.get('ingredientBrand')?.setErrors({required_at_least: true});
return ({required_at_least: true});
} else {
control.get('ingredientName')?.setErrors(null);
control.get('ingredientFlavor')?.setErrors(null);
control.get('ingredientBrand')?.setErrors(null);
}
if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) {
control.get('ingredientName')?.setErrors({not_the_same: true});
control.get('ingredientBrand')?.setErrors({not_the_same: true});
return ({not_the_same: true});
}
}
return null;
}
}
我也收到同样的错误,我做了以下更改。
确保您的验证器函数签名与此匹配。 (一个接收控件并同步 returns 验证错误映射(如果存在)的函数,否则为空。)
- 函数Your_Function_Name(对象名称:AbstractControl):ValidationErrors |无效的
{
}
您可以像这样更改表单生成器中的代码。
- const formOptions: AbstractControlOptions = { validators: Your_Function_Name };
并在 formbuilder 对象中像这样在 formOptions 对象上方传递
- this.formObject = this.formBuilder.group({
全名:['', [Validators.required]]
}, 表单选项);
虽然 的答案解释完整,但我想添加一个不同的答案,指出要点:
- 指定验证器函数时,只指定函数名(即,不带任何参数)
- 该验证器函数必须接受一个且仅一个
AbstractControl
类型的参数
- 验证器函数必须 return
{key: value}
或 null
,但 而不是 始终 null
。 Return null
当没有错误显示时。
这是在 RegisterPage.ts 中声明的表单示例:
import { Component, OnInit } from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormControl,
FormGroup,
Validators,
} from '@angular/forms';
@Component({
selector: 'app-register',
templateUrl: './register.page.html',
styleUrls: ['./register.page.scss'],
})
export class RegisterPage implements OnInit {
form: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.createForm();
}
createForm() {
this.form = this.fb.group({
matchEmail: this.fb.group(
{
//email textfield
email: new FormControl(
'',
Validators.compose([
Validators.required,
Validators.maxLength(64),
Validators.email,
])
),
//confirm email textfield
confirmEmail: new FormControl(''),
},
{ validators: this.matchEmail }
),
});
}
}
验证器函数将创建一个名为 mismatch
的新错误类型,可以插入到 RegisterPage.ts 文件中:
matchEmail(group: AbstractControl) {
let email: string = group.get('email').value;
let confirmEmail: string = group.get('confirmEmail').value;
if (email.localeCompare(confirmEmail) != 0) {
//error
group.get('confirmEmail')?.setErrors({ mismatch: true });
return { mismatch: true };
} else {
//no error, return null (don't return { mismatch: false })
return null;
}
}
你的 html 可以是这样的(你不能直接访问 confirmEmail
,它必须通过它所属的组 matchEmail.confirmEmail
):
<div *ngIf="form.get('matchEmail.confirmEmail').hasError('mismatch')
&& (form.get('matchEmail.confirmEmail').dirty ||
form.get('matchEmail.confirmEmail').touched)">
<small>Confirmation email doesn't match</small>
</div>
我将我的项目迁移到 angular 11,我注意到我添加的全局验证使 FormBuilder.group
已弃用并显示以下消息:
group is deprecated: This api is not typesafe and can result in issues with Closure Compiler renaming.
Use the `FormBuilder#group` overload with `AbstractControlOptions` instead.
所以这已被弃用:
ingredientForm = this.fb.group({
ingredientType: ['', Validators.required],
ingredientFlavor: [''],
isMultiFlavor: [''],
ingredientBrand: [''],
ingredientName: [''],
imageFile: ['']
}, {validators: [ValidateThirdNumber.validate]});
没有 validators
选项就不是。
我的 ValidateThirdNumber
验证者:
class ValidateThirdNumber {
static validate(control: AbstractControl): void {
if (control) {
const isMultiFlavor = control.get('isMultiFlavor')?.value;
const ingredientFlavor = control.get('ingredientFlavor')?.value;
const ingredientBrand = control.get('ingredientBrand')?.value;
const ingredientName = control.get('ingredientName')?.value;
if (isMultiFlavor && ingredientFlavor.trim().length === 0) {
control.get('ingredientFlavor')?.setErrors({required_if: true});
} else {
control.get('ingredientFlavor')?.setErrors(null);
}
if (!ingredientFlavor && !ingredientBrand && !ingredientName) {
control.get('ingredientName')?.setErrors({required_at_least: true});
control.get('ingredientFlavor')?.setErrors({required_at_least: true});
control.get('ingredientBrand')?.setErrors({required_at_least: true});
} else {
control.get('ingredientName')?.setErrors(null);
control.get('ingredientFlavor')?.setErrors(null);
control.get('ingredientBrand')?.setErrors(null);
}
if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) {
control.get('ingredientName')?.setErrors({not_the_same: true});
control.get('ingredientBrand')?.setErrors({not_the_same: true});
}
}
}
}
如何使用 AbstractControlOptions 重载它?
问题描述
从 documentation 我们看到两个不同的行与 group()
函数
group(controlsConfig: { [key: string]: any; }, options?: AbstractControlOptions): FormGroup
AND
group(controlsConfig: { [key: string]: any; }, options: { [key: string]: any; }): FormGroup
第二个定义已弃用
这几行的区别是options?: AbstractControlOptions
和options: { [key: string]: any; }
要理解 angular 抛出此错误的原因,我们现在将考虑 AbstractControlOptions
interface AbstractControlOptions {
validators?: ValidatorFn | ValidatorFn[] | null
asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null
updateOn?: 'change' | 'blur' | 'submit'
}
我们继续分解问题,注意到这个结构和你的结构之间的区别是ValidatorFn[]
interface ValidatorFn {
(control: AbstractControl): ValidationErrors | null
}
总的来说,在您的情况下会引发错误,因为您的 Validator
函数应该控制 return ValidationErrors | null
。在行 validate(control: AbstractControl): void
中,您的代码实际上 returns void
但预期 return a ValidationError | null
解决方案
从问题描述来看,解决方法是简单修改ValidatorFn
确保您的 ValidatorFn
return 是 ValidationError
或者如果没有错误 return 是 null
来自 ValidationErrors defination
type ValidationErrors = {
[key: string]: any;
};
您将需要 return 键值对对象,例如 {required_if: true}
我们可以按预期添加 return 语句来更改您的代码
class ValidateThirdNumber {
static validate(control: AbstractControl): ValidationErrors | null {
if (control) {
const isMultiFlavor = control.get('isMultiFlavor')?.value;
const ingredientFlavor = control.get('ingredientFlavor')?.value;
const ingredientBrand = control.get('ingredientBrand')?.value;
const ingredientName = control.get('ingredientName')?.value;
if (isMultiFlavor && ingredientFlavor.trim().length === 0) {
control.get('ingredientFlavor')?.setErrors({required_if: true});
return ({required_if: true});
} else {
control.get('ingredientFlavor')?.setErrors(null);
}
if (!ingredientFlavor && !ingredientBrand && !ingredientName) {
control.get('ingredientName')?.setErrors({required_at_least: true});
control.get('ingredientFlavor')?.setErrors({required_at_least: true});
control.get('ingredientBrand')?.setErrors({required_at_least: true});
return ({required_at_least: true});
} else {
control.get('ingredientName')?.setErrors(null);
control.get('ingredientFlavor')?.setErrors(null);
control.get('ingredientBrand')?.setErrors(null);
}
if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) {
control.get('ingredientName')?.setErrors({not_the_same: true});
control.get('ingredientBrand')?.setErrors({not_the_same: true});
return ({not_the_same: true});
}
}
return null;
}
}
我也收到同样的错误,我做了以下更改。
确保您的验证器函数签名与此匹配。 (一个接收控件并同步 returns 验证错误映射(如果存在)的函数,否则为空。)
- 函数Your_Function_Name(对象名称:AbstractControl):ValidationErrors |无效的 { }
您可以像这样更改表单生成器中的代码。
- const formOptions: AbstractControlOptions = { validators: Your_Function_Name };
并在 formbuilder 对象中像这样在 formOptions 对象上方传递
- this.formObject = this.formBuilder.group({ 全名:['', [Validators.required]] }, 表单选项);
虽然
- 指定验证器函数时,只指定函数名(即,不带任何参数)
- 该验证器函数必须接受一个且仅一个
AbstractControl
类型的参数
- 验证器函数必须 return
{key: value}
或null
,但 而不是 始终null
。 Returnnull
当没有错误显示时。
这是在 RegisterPage.ts 中声明的表单示例:
import { Component, OnInit } from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormControl,
FormGroup,
Validators,
} from '@angular/forms';
@Component({
selector: 'app-register',
templateUrl: './register.page.html',
styleUrls: ['./register.page.scss'],
})
export class RegisterPage implements OnInit {
form: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.createForm();
}
createForm() {
this.form = this.fb.group({
matchEmail: this.fb.group(
{
//email textfield
email: new FormControl(
'',
Validators.compose([
Validators.required,
Validators.maxLength(64),
Validators.email,
])
),
//confirm email textfield
confirmEmail: new FormControl(''),
},
{ validators: this.matchEmail }
),
});
}
}
验证器函数将创建一个名为 mismatch
的新错误类型,可以插入到 RegisterPage.ts 文件中:
matchEmail(group: AbstractControl) {
let email: string = group.get('email').value;
let confirmEmail: string = group.get('confirmEmail').value;
if (email.localeCompare(confirmEmail) != 0) {
//error
group.get('confirmEmail')?.setErrors({ mismatch: true });
return { mismatch: true };
} else {
//no error, return null (don't return { mismatch: false })
return null;
}
}
你的 html 可以是这样的(你不能直接访问 confirmEmail
,它必须通过它所属的组 matchEmail.confirmEmail
):
<div *ngIf="form.get('matchEmail.confirmEmail').hasError('mismatch')
&& (form.get('matchEmail.confirmEmail').dirty ||
form.get('matchEmail.confirmEmail').touched)">
<small>Confirmation email doesn't match</small>
</div>