Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/forms/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms Angular:用于实现嵌套表单的复合ControlValueAccessor_Forms_Angular - Fatal编程技术网

Forms Angular:用于实现嵌套表单的复合ControlValueAccessor

Forms Angular:用于实现嵌套表单的复合ControlValueAccessor,forms,angular,Forms,Angular,在Angular Connect 2017演示文稿中介绍了用于实现嵌套表单的ControlValueAccessor的组成 在本演示中,演讲者展示了一种实现自定义表单控件的方法,该控件具有多个值(不仅是单个字符串值,而且具有两个字符串字段,如street和city)。我想实现它,但我被卡住了。示例应用程序在这里,有人知道我应该更正什么吗 父组件 @Component({ selector: 'my-app', template: ` <h1>Form</h1

在Angular Connect 2017演示文稿中介绍了用于实现嵌套表单的ControlValueAccessor的组成

在本演示中,演讲者展示了一种实现自定义表单控件的方法,该控件具有多个值(不仅是单个字符串值,而且具有两个字符串字段,如street和city)。我想实现它,但我被卡住了。示例应用程序在这里,有人知道我应该更正什么吗

父组件

@Component({
  selector: 'my-app',
  template: `
    <h1>Form</h1>
    <form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" novalidate>
      <label>name</label>
      <input formControlName="name">
      <app-address-form formControlName="address"></app-address-form>
      <button>submit</button>
    </form>
  `,
})
export class AppComponent  {
  @Input() name: string;
  submitData = '';
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = fb.group({
      name: 'foo bar',
      address: fb.group({
        city: 'baz',
        town: 'qux',
      })
    });
  }

  onSubmit(v: any) {
    console.log(v);
  }
}
@Component({
  selector: 'app-address-form',
  template: `
    <div [formGroup]="form">
      <label>city</label>
      <input formControlName="city" (blur)="onTouched()">
      <label>town</label>
      <input formControlName="town" (blur)="onTouched()">
    </div>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => AddressFormComponent)
    }
  ]
})
export class AddressFormComponent implements ControlValueAccessor {
  form: FormGroup;

  onTouched: () => void = () => {};

  writeValue(v: any) {
    this.form.setValue(v, { emitEvent: false });
  }

  registerOnChange(fn: (v: any) => void) {
    this.form.valueChanges.subscribe(fn);
  }

  setDisabledState(disabled: boolean) {
    disabled ? this.form.disable() : this.form.enable();
  }

  registerOnTouched(fn: () => void) {
    this.onTouched = fn;
  }
}

我认为FormGroup实例应该以某种方式注入嵌套表单组件…

两个问题,在您的
AppComponent
上,将您的
FormBuilder
更改为:

this.form = fb.group({
  name: 'foo bar',
  address: fb.control({ //Not using FormGroup
    city: 'baz',
    town: 'qux',
  })
});
AddressFormComponent
上,您需要像这样初始化FormGroup:

form: FormGroup = new FormGroup({
    city: new FormControl,
    town: new FormControl
});
这是您的示例的分支:

我们(在工作中)遇到了这个问题,并尝试了几个月不同的事情:如何正确处理嵌套表单

实际上,
ControlValueAccessor
似乎是一个不错的选择,但我们发现它非常冗长,而且构建嵌套表单的时间相当长。由于我们在应用程序中经常使用这种模式,我们最终花了一些时间进行调查,并尝试提出更好的解决方案。我们称之为ngx子表单,它是一种回购协议,可在(+source code on)上获得

基本上,要创建子表单,您所要做的就是扩展我们提供的类,并传递FormControls。就这样

我们已经更新了我们的代码库以使用它,我们对此非常高兴,所以您可能想尝试一下,看看它对您有什么好处:)

每件事都在报告中解释


PS:我们这里还有一个完整的演示

你能在问题中发布你的代码吗?你到底有什么问题?@roelofs谢谢,我更新了帖子。哇,我必须使用fb.control而不是fb.group。我觉得很奇怪,因为它的实例被引用为FormGroup,但它正在工作!!谢谢@12seconds.fmm,如果FormArray是嵌套的,我就得到了错误。有什么问题@adwd我认为自定义控件作为控件是很自然的。:)自定义控件的值只是一个复杂的对象。@penleychan验证有问题。如果我们将嵌套表单视为FormControl,则主表单不知道嵌套表单的有效性。这里是演示。尝试清除必填字段。我们如何解决这个问题?@TarasHupalo,我建议你看看我的其他答案来实现这一点,如果你投反对票,我很好,但如果你能解释为什么你认为我写了一个糟糕的答案,那就太好了。
form: FormGroup = new FormGroup({
    city: new FormControl,
    town: new FormControl
});