繁体   English   中英

在不同的 Angular 组件中重用 FormBuilder 验证器

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM