[英]Reuse FormBuilder Validator in different Angular Components
我背后有一个组件、表单和业务验证器。 此外,还有显示表单如何呈现的 html。
问题是,如果有人想使用具有相同验证器的表单构建器,但是完全不同的 html 呈现怎么办?
如何分离下面的表单,这样表单控件和验证器是分开的,而不是与html格式强耦合?
我们可以导出为类、输入/输出或 ControlValueAccessor 吗?
目前这是一个组件。 注意:需要能够处理更复杂的验证器(例如,需要城市/州或邮政编码,其中之一)
客户信息组件:
打字稿
constructor(
private formBuilder: FormBuilder,
private cdr: ChangeDetectorRef
) {
this.addressform = this.formBuilder.group({
'firstName': [null, [Validators.maxLength(32)]],
'lastName': [null, [Validators.maxLength(32)]],
'phone': [null, [Validators.maxLength(32)]],
'streetName': [null, [Validators.required, Validators.maxLength(64)]],
'streetType': [null, [Validators.maxLength(8)]],
'city': [null, [Validators.maxLength(32)]],
'state': [null, [Validators.maxLength(16)]],
'postalCode': [null, [Validators.maxLength(16)]],
}, { validator: atLeastOneLocationRequired })
// City,State or PostalCode Required
export function atLeastOneLocationRequired(group : FormGroup) : {[s:string ]: boolean} {
var cityCtrl = group.controls.city;
var stateCtrl = group.controls.state;
var postalCodeCtrl = group.controls.postalCode;
if (cityCtrl != undefined && stateCtrl != undefined && postalCodeCtrl != undefined)
if (!(((cityCtrl.value && cityCtrl.value.length) && (stateCtrl.value && stateCtrl.value.length)) || (postalCodeCtrl.value && postalCodeCtrl.value.length)))
return { invalid: true };
}
HTML表单生成器稍后将需要不同的 html 格式。
<div class = "propertysitusaddress">
<form [formGroup]="addressform">
<div class = "propertysiteaddresscontainer column">
<div class = "row title">
Address
</div>
<div class = "row">
<app-input-textboxc formControlName = "firstName"> </app-input-textbox>
<app-input-textbox formControlName = "lastName"> </app-input-textbox>
<app-input-textbox formControlName = "phone"> </app-input-textbox>
</div>
<div class = "row">
<app-input-textbox formControlName = "streetName"> </app-input-textbox>
<app-input-textbox formControlName = "city"> </app-input-textbox>
<app-input-textbox formControlName = "state"> </app-input-textbox>
</div>
<div class = "row">
<app-input-textbox formControlName = "postalCode"> </app-input-textbox>
</div>
</div>
它经常被提及在 Angular 中分离智能组件和展示组件。
我在我的一个项目中实现了这一点。
方法#1
为表单字段创建自定义通用模型。 在您的情况下,每个字段都有一个名称和 maxLength 属性。 所以你的表单字段模型看起来像这样。
export class FormFieldModel {
name: string;
label: string;
fieldConfig: CustomFieldConfig;
}
export class CustomFieldConfig {
/** whether the property field is editable or not within the form */
editable: boolean;
/** optional collection of validators for the form field */
validators?: ValidatorFn[];
/** whether the form field is required */
required = true;
maxlength?: number;
/** the control type for the form field */
type?: 'select' | 'date' | 'number' | 'text' | 'checkbox';
patternValidationMessage?: string;
options?: any[];
}
现在在您需要表单的每个组件中。 使用上述模型构建所有字段的数组。
例子:
const fields = FormFieldModel[] = [
{
name: 'firstName',
label: 'First Name',
fieldConfig: {
maxLength: 32
// other custom props.
},
{
name: 'lastName',
label: 'Last Name',
fieldConfig: {
maxLength: 32
// other custom props.
}
}
正如前面评论中提到的,创建一个服务来创建表单,或者也可以在单个组件级别创建它。
createForm(formList: FormFieldModel []) {
const form = this.formBuilder.group({ });
formList.forEach(field => {
const validators = field.formConfig ? field.formConfig.validators : undefined;
form.addControl(field.name, this.formBuilder.control(field.value, validators));
});
this.addressForm= form; // if this method is at component level
or
return form; // if this method is at service layer.
}
这样,它也将有助于您的 html。 现在,在您的 html. 您可以遍历字段。
<form [formGroup]="addressForm">
<div *ngFor="let field in fields>
<app-input-textbox formControlName = "field.name"> </app-input-textbox> // you can have a custom component that takes in individual field object and display it accordingly.
</div>
</form>
方法#2:
只需将 FormGroup 和 Formbuilder 放入导出类即可。 您可以利用您的代码,并在新组件中调用此类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.