如何在angular8中使用反应式表单将模型绑定到formbuilder上?

问题描述 投票:0回答:1

我在我的应用程序中使用了反应式表单,并使用formcontrolName绑定到html。但是现在,我不需要在formbuilder中声明属性,而是需要调用一个模型,并将该模型分配给formbuilder,并在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;
}

DEMO

angular angular-reactive-forms reactive
1个回答
1
投票

根据评论,听起来你想要一个基于模型的动态表单...没有 "开箱即用 "的解决方案。你可以写你自己的表单模型。

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: { },
}

然后你可以写一个服务来生成基于表单模型的表单组... ...

@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 接口,typecript会向你喊话,让你用字段信息更新相应的表单模型......虽然更新不会从模型更新中 "自动 "流出,但你至少在表单中拥有一些类型安全。我个人在这里就不说了。

接下来的这个部分并不完美,我也不喜欢它,但是如果你真的希望下一步能从类定义中或多或少地实现自动更新,你可以写一个函数从类中建立一个默认的表单模型,就像这样。

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

这需要2件事情,1,你的类必须为每个字段指定一个默认值,没有默认值的字段不会被包含。(这就引入了对字段有默认值的隐性依赖,这也是我不喜欢这种方法的原因,不过,如果你写了一个没有默认值或构造函数赋值的属性的类,你可以配置ts来吼你)。

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

2,对象构造函数必须不接受任何参数,但如果你试图在这种情况下滥用它,TS会对你大喊大叫。

函数可以这样使用。

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

这样你就可以使用默认字段, 也可以为特定字段提供覆盖。

最后,你也可以利用这个表单模型来建立一个模板,但这是一个更大的任务。

这是一个全部实现的突击项目(我还提前清理了控制器的代码)。https:/stackblitz.comeditgithub-ck3u8u-qtnasc?file=src%2Fapp%2Fuser-table%2Fuser-table.validators.ts。


0
投票

你必须在FormGroup表单控件中使用patchValue来绑定你的模型。

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

这是正确的,当你得到UserFormDetails对象时,你必须把它传递给表单,你必须做.PatchValue。

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

而当你必须将表单控件的值传递给对象时。

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

等等...


0
投票

我想这可能是你正在寻找的解决方案。

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);
}

这种方式满足了你对 "绑定 "的需求,这不是一个真正的绑定,因为框架不允许这样的事情,但它允许你从对象模型值映射到创建反应式表单模型。

请看在添加一个extraField后,表单如何拾取该控件及其值。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.