嵌套表单组件在提交时未设置初始值

时间:2019-06-14 05:52:46

标签: angular angular-reactive-forms reactive-forms

我正在尝试使用ControlValueAccessors以反应形式实现带有角度的嵌套形式组件,并且我一直遵循本指南:https://blog.angularindepth.com/angular-nested-reactive-forms-using-cvas-b394ba2e5d0d

除了一个主要问题外,我已经可以完成所有工作。如果我的表单是预先填充的,即,该表单用于编辑现有数据而不是创建表单,那么如果相应的子组件表单值未更改,则提交时不会在表单的值上设置初始数据。

我在以下链接上有一个示例设置(打开右下角的控制台): https://stackblitz.com/edit/angular-nested-forms-cva-izbrht

如您所见,如果立即按Submit,则表单值包含两个属性,该值只是两个空字符串。如果您编辑例如名字,然后提交,您将看到basicInfo属性现在已经正确设置了其值。

5 个答案:

答案 0 :(得分:1)

@langen,对我来说,它使用[formGroup]和[formControl]。这是question in stackoverflowstackblitz

的注释

我的主要人

<form [formGroup]="formGroup">
  <app-personal-details-form [formGroup]="formGroup"></app-personal-details-form>
</form>
//It's in main where I create the formGroup:
formGroup = new FormGroup(
    {
      name: new FormGroup({
        firstname: new FormControl(null, { validators: [Validators.required] }),
        lastname: new FormControl(null, { validators: [Validators.required] }),
      }),
      gender: new FormControl(null, { validators: [Validators.required] }),
      address: new FormGroup({
        streetaddress: new FormControl(null, { validators: [Validators.required] }),
        city: new FormControl(null, { validators: [Validators.required] }),
        state: new FormControl(null, { validators: [Validators.required] }),
        zip: new FormControl(null, { validators: [Validators.required] }),
        country: new FormControl(null, { validators: [Validators.required] })
      }),
      phone: new FormGroup({
        phone: new FormControl(null, { validators: [Validators.required] }),
        countrycode: new FormControl(null, { validators: [Validators.required] }),
      })

    })

其余部分:

个人细节

<div [formGroup]="formGroup">
    <app-name-form [formGroup]="formGroup.get('name')"></app-name-form>
    <select formControlName="gender">
    <option *ngFor="let gender of Gender | keyvalue" [value]="gender.value">{{ gender.value }}</option>
  </select>
  <app-address-form [formGroup]="formGroup.get('address')"></app-address-form>
  <app-phone-form [formGroup]="formGroup.get('phone')"></app-phone-form>
</div>
//and 
@Input() formGroup:FormGroup;

地址表格

<div [formGroup]="formGroup">
  <input type="text" placeholder="Street address" formControlName="streetaddress">
  <span *ngIf="formGroup.get('streetaddress').invalid">*</span>
  <input type="text" placeholder="City" formControlName="city">
  <input type="text" placeholder="State" formControlName="state">
  <input type="text" placeholder="Zip" formControlName="zip">
  <input type="text" placeholder="Country" formControlName="country">
</div>
//and 
@Input() formGroup;

姓名表格

<div [formGroup]="formGroup">
  <input type="text" placeholder="First name" formControlName="firstname">
  <input type="text" placeholder="Last name" formControlName="lastname">
</div>
//and
    @Input() formGroup;

答案 1 :(得分:0)

我通过在父组件中创建完整的FormGroup,然后将子表单作为输入传递给子组件来解决此问题。这消除了使用ControlValueAccessors的需要。

我对此解决方案不满意,因为我希望子组件负责创建其表单组,但是我找不到解决我问题的任何解决方案,所以现在必须这样做。

答案 2 :(得分:0)

@Lagen,当您具有自定义表单控件时,您需要在组件中添加Feed。例如在您的billing-info.component中。

public nestedForm: FormGroup = new FormGroup({
  basicInfo: new FormControl({fname:"Carl init",email:"myemail init@whatever.com"}),
  address: new FormControl({addressLine:"My address",areacode:'12345 new'})
  });

当然,您可以删除组件中的初始化值。

是的,FormControl可以存储一个对象。您可以将customForm控件视为“黑匣子”。有趣的是您提供的值和获得的值-而不是它的产生方式-(就我个人而言,我认为使用自定义表单控件创建嵌套表单是使用大锤来破解螺母)

答案 3 :(得分:0)

在创建父表单本身时,可以将默认值传递给嵌套表单。这样可以解决问题the form is used to edit existing data instead of creating, then the initial data is not set on the form's value upon submit if the corresponding child component form values hasn't been changed.

this.nestedForm= new FormGroup({
  basicInfo: defaultValues ? new FormControl(defaultValues.basicInfo) : new FormControl(),
  address: defaultValues ? new FormControl(defaultValues.address) : new FormControl()
});

因此,这里是defaultValues对象,用于设置默认值,例如https://blog.angularindepth.com/angular-nested-reactive-forms-using-cvas-b394ba2e5d0d

const defaultValues = {
  basicInfo: {
    fname: 'suchin',
    lname: 'b'
  },
  address: {
    addressLine: 'Home',
    areacode: 'Test Code'
  }
}

答案 4 :(得分:0)

这是我的解决方法,

将registerOn更改为此:

registerOnChange(fn) {
  this.onChange = fn;
}

然后在子组件ngOnInit挂钩中调用onChange方法,如下所示:

 setTimeout(() => {
  this.onChange(this.form.value);
});

完成!请注意使用setTimeout包装,否则它将无法正常工作。