繁体   English   中英

如何在angular8中使用反应性forms将model绑定到formbuilder

[英]How to bind model to formbuilder using reactive forms in angular8

我在我的应用程序中使用了反应式 forms 并使用 formcontrolName 绑定到 html。 但是现在我不需要在表单构建器中声明属性,而是需要调用 model 并将 model 分配给表单构建器并在 html 中使用它。 我浏览了许多链接,但没有找到任何根据我的要求工作的方法。

HTML:

<div class="tab-pane fade h-100 active show" id="tab-user_1" role="tabpanel" aria-labelledby="user_1"
    *ngIf="userInfoForm" [formGroup]="userInfoForm">
    <div class="row">
      <div class="col-6">
        <div class="form-group">
          <label for="">Agent Code <span class="text-danger">*</span></label>
          <input type="text" formControlName="agentCode" class="form-control">
        </div>
      </div>
</div>

TS:

 this.userInfoForm = this.FB.group({
        Id: 0,
        agentCode: this.agentCode,
        userName: [''],
        firstName: [''],
        middleName: '',
        lastName: [''],
        department: [''],
      });
      this.userInfoForm.controls['agentCode'].disable();

model.ts:

export class UserFormDetails {
   Id: number;
   agentCode: number;
   userName: string;
   firstName: string;
   middleName: string;
   lastName: string;
   department: string;
}

演示

根据评论,听起来您想要一个基于 model 的动态表单......没有“开箱即用”的解决方案可以做到这一点。 您可以编写自己的表格 model:

interface MyFormModelField {
  initial?: {
    value: any,
    disabled: boolean
  },
  controlOptions?: AbstractControlOptions
  // anything you find useful really?
}

export type MyFormModel<T> = Record<keyof T, MyFormModelField>

然后像这样实现它:

const USER_FORM_MODEL: MyFormModel<UserFormDetails> = {
    Id: { },
    agentCode: {
        initial: {
          value: '',
          disabled: true
        },
        controlOptions: {
          validators: Validators.required
        }
    },
    userName: { },
    firstName: { },
    middleName: { },
    lastName: { },
    department: { },
}

那么您可以编写一个服务来基于 model 形式的实例生成表单组...

@Injectable({providedIn: 'root'})
export class MyFormBuilder {
  constructor(private: fb) { }

  buildForm<T>(formModel: MyFormModel<T>) {
    const fg = Object.keys(formModel).reduce((grp, k) => {
      const fld = formModel[k];
      return Object.assign(grp, {
        [k]: [fld.initial || '', fld.controlOptions]
      })
    }, {});
    return this.fb.group(fg);
  }
}

现在,每当您更改UserFormDetails界面时,typescript 都会对您大喊大叫,用字段信息更新相应的表单 model ......虽然更新不会“自动”从 Z20F35E630DAF44DBFA4C3F68F5 类型中更新,但您至少有一些更新forms 的安全性。 我个人会在这里停下来。

下一部分并不完美,我也不喜欢它,但是如果您真的希望下一步从 class 定义中或多或少地自动执行,您可以编写 function 来构建默认表单 Z20F35E630DAF494DDB85FC来自 class,如下所示:

function buildDefaultFormModel<T>(model: new () => T) {
  return Object.keys(new model()).reduce((form, k) => {
      return Object.assign(form, {[k]: {}})
  }, {} as MyFormModel<T>)
}

这需要两件事,1,您构建表单的 class 必须为每个字段指定默认值,不包括没有默认值的字段。 (这引入了对具有默认值的字段的隐藏依赖,这就是我不喜欢这种方法的原因,但是,如果您编写的 class 具有没有默认值或构造函数分配的属性,您可以配置 ts 对您大喊大叫):

class UserFormDetails {
   Id: number = 0;
   agentCode: number = 0;
   userName: string = '';
   firstName: string = '';
   middleName: string = '';
   lastName: string = '';
   department: string = '';
}

2、object构造函数不能带参数。 但是如果你在这种情况下试图滥用它,TS 会对你大喊大叫。

function 可以这样使用:

const USER_FORM_MODEL: MyFormModel<UserFormDetails> = {
  ...buildDefaultFormModel(UserFormDetails),
  ...{
    agentCode: {
      initial: {
        value: '',
        disabled: true
      },
      controlOptions: {
        validators: Validators.required
      }
    },
  }
}

通过这种方式,您可以使用默认字段,还可以为特定字段提供覆盖。

最后,您还可以利用此表格 model 来构建模板,但这是一项更大的任务。

这是所有实现的闪电战(我继续清理 controller 代码): https://stackblitz.com/edit/github-ck3u8u-qtnasc?file=src%2Fapp%2Fuser-table%2Fuser验证器.ts

您必须使用 patchValue 在 FormGroup 表单控件中绑定您 model 。

this.userInfoForm = this.FB.group({
        Id: 0,
        agentCode: this.agentCode,
        userName: [''],
        firstName: [''],
        middleName: '',
        lastName: [''],
        department: [''],
      });

这是对的。 当您获得 UserFormDetails object 时,您必须将其传递给您必须执行的表单:

 this.userInfoForm.patchValue({
   'Id': UserFormDetails.id 
    ...
})

当您必须将表单控件值传递给 object 时:

 this.UserFormDetail.id = this.userInfoForm.get('Id').value

ETC...

我认为这可能是您正在寻找的解决方案:

private initUserForm() {
   // mapping the object into the form model
   this.userInfoForm = this.FB.group({ ...this.userDetails });

   // if you want to add validators or disable buttons...
   this.userInfoForm.controls.agentCode.setValidators(Validators.required); // adding validations
   this.userInfoForm.controls.agentCode.disable();
   // console.log(this.userInfoForm.controls);
}

这种方式涵盖了您对“绑定”的需求,这不是真正的绑定,因为框架不允许这样的事情,但它允许您从 object 模型/值中 map 以创建反应形式 Z20F35E630DAF44DDBFA4C3F68FZ539。


查看添加 extraField 后,forms 如何获取该控件及其值:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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