我后面有一个组件,表单和业务验证器。另外,有显示表单呈现方式的html。
问题是,如果有人想使用带有相同验证器的formbuilder,而又使用完全不同的html呈现方式,怎么办?
如何分隔下面的表单,以便使表单控件和验证器分开,并且与html格式没有强烈的关联?
我们可以导出为类,输入/输出或ControlValueAccessor吗?
当前,这是一个组件。 注意:将需要具有处理更复杂的验证器的能力(例如,所需的城市/州或邮政编码,一个或另一个)
CustomerInfo.component:
打字稿
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 。formbuilder稍后将需要其他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中的智能组件和表示组件分开。
答案 0 :(得分:2)
我在一个项目中实现了这一点。
方法1
为表单字段创建自定义通用模型。 在您的情况下,每个字段都有一个name和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放入导出类中即可。您可以利用您的代码,并在新组件中调用此类。