如何根据提供的 JSON 数据使用 angular 构建嵌套反应式表单结构

How to build the Nested Reactive Form structure using angular based on the JSON Data provided

我是 angular 的新手。下面是我从邮递员的 GET 调用中获得的 JSON 数据。我正在尝试使用此

构建表单
  data = {
    headline: [
      {
        language: 'en',
        headlineText: 'example headline',
      },
    ],
    bodyText: [
      {
        language: 'en',
        bodyText: 'example bodytext',
      },
    ],
    location: {
      name: 'mkontheway',
      openingHours: [
        {
          day: 'Mon-frd',
          timing: '10.00PM-9AM',
        },
      ],
      address: {
        postCode: 'test',
        country: 'test',
      },
    },
  };

但是这里 Day 和 Timing 字段重复了 2 次。由于嵌套的表单结构,我无法正确控制这两个字段。请有人建议我在 angular.

中构建复杂嵌套表单结构的解决方案

提前致谢。

这里是堆栈闪电战 link

Angular Nested Form

这里有嵌套的表单组和表单数组。请建议我如何使用 angular 反应形式

来实现这种嵌套形式的实现

我参考了这个堆栈闪电战示例 Reference Stack blitz

你只需要在 location

的 openingHours 中创建一个 empty formArray
   this.createAppForm = this.fb.group({
      ...
      location: this.fb.group({
        name: ['', Validators.required],
        openingHours: this.fb.array([]), //<--this is an "empty" formAray
        address: this.fb.group({
           ...
        }),
      }),
    });

但是(总是有一个但是)看到你的代码你有很多重复来创建不同的 FormGroups。重复代码会让我们早早陷入困境。

所以我们将创建 return 构成您的 FormGroup

的 formGroups 的函数

假设你有一些像

  setHeadLine(data: any = null) {
    data = data || { language: null, headlineText: null };
    return this.fb.group({
      headlineText: data.headlineText,
      language: data.language,
    });
  }

  setBodyText(data: any = null) {
    data = data || { bodyText: null, language: null };
    return this.fb.group({
      bodyText: data.bodyText,
      language: data.language,
    });
  }

  setAddress(data: any = null) {
    data = data || { postCode: null, country: null };
    return this.fb.group({
      postCode: [data.postCode, Validators.required],
      country: [data.country, Validators.required],
    });
  }

  setOpeningHour(data: any = null) {
    data = data || { day: null, timing: null };
    return this.fb.group({
      day: [data.day, Validators.required],
      timing: [data.timing, Validators.required],
    });
  }

  setLocation(data: any = null) {
    console.log(data);
    data = data || { name: null, openingHours: null, address: null };
    return this.fb.group({
      name: [data.name, Validators.required],
      openingHours: this.fb.array(
        data.openingHours
          ? data.openingHours.map((x) => this.setOpeningHour(x))
          : []
      ),
      address: this.setAddress(data.address),
    });
  }

查看“setLocation”如何调用函数 setAddress 来创建 formGroup 地址以及 openingHours 如何是 this.fb.array。如果 data.openingHours 是一个数组,将对象数组转换为 formGroups 数组并创建 formArray,否则 return 一个空数组

最后你创建了一个函数 return 你的 formGroup

  setFormGroup(data: any = null) {
    data = data || { headline: null, bodyText: null, location: null };
    return this.fb.group({
      headline: this.fb.array(
        data.headline ? data.headline.map((x) => this.setHeadLine(x)) : []
      ),
      bodyText: this.fb.array(
        data.bodyText ? data.bodyText.map((x) => this.setBodyText(x)) : []
      ),
      location: this.setLocation(data.location),
    });
  }

我这样你就不重复代码了。在构造函数中你可以写

 this.createAppForm = this.setFormGroup(this.data);

添加 FormGroup 时只需调用以下函数:

  addHeadline() {
    this.getHeadlineFormData().push(this.setHeadLine())
  }

  addBodyText() {
    this.getBodyTextFormData().push(this.setBodyText())
  }

  addOpeningHours() {
    this.getopeningHoursFormData().push(this.setOpeningHour())
  }

嗯,(最后这只是一个建议)我认为使用“getter”代码会变得更清晰,所以如果你替换

//replace
  getHeadlineFormData() {
    return <FormArray>this.createAppForm.get('headline');
  }
//by 
  get headlineFormData() {
    return <FormArray>this.createAppForm.get('headline');
  }

//replace
  getBodyTextFormData() {
    return <FormArray>this.createAppForm.get('bodyText');
  }
//by
  get bodyTextFormData() {
    return <FormArray>this.createAppForm.get('bodyText');
  }

//replace
  getLocationFormData() {
    return <FormArray>this.createAppForm.get('location');
  }
//by
  get locationFormData() {
    return <FormArray>this.createAppForm.get('location');
  }

//and replace
  getopeningHoursFormData() {
    return <FormArray>this.createAppForm.get('location')?.get('openingHours');
  }
//by
  get openingHoursFormData() {
    return <FormArray>this.createAppForm.get('location')?.get('openingHours');
  }

您可以使用 this.headlineFormData 而不是 this.getHeadlineFormData() - 请注意,使用 getter 您不需要写括号。并在 html headlineFormData.controls 而不是 getHeadlineFormData().controls -再次看到使用“getter”你不写括号。

你的forked stackbliz