1
votes

I am stuck with a logical issue here about using Reactive Forms in Angular.

I have an object similar to the one below.

interface MenuGroup {
  title: string;
  menuItems: MenuItem[];
};

interface MenuItem {
  title: string;
  status: string;
};

interface RoleModel {
  roleName: string;
  menuGroup: MenuGroup[];
};

role: RoleModel

Menu Item is basically a check box in the UI.

List of Menu Items belonging to its Menu Group will be displayed under its title.

Like,

Menu Group Name 1. Menu Item 1 --> CheckBox 2. Menu Item 2 --> CheckBox

So, now the question..

I need to build a Reactive Form for this problem. I am not able to come up with a solution. I am trying to build nested FormArrays but in vain.

Any help would be appreciated!

1
I've created a example in stackblitz. But it's not complete.Anuradha Gunasekara
That's a lot of effort. Thank you! But can you explain a bit? Or may be provide links to the resource? Thanks!Srihari GouthamGr

1 Answers

0
votes

Here is what I suggest. I assume that your role varible is equal to something like this object.

this.role = {
      roleName: 'Test Role name',
      menuGroup: [
        {
          title: 'menu group 1',
          menuItems: [
            {
              title: 'group 1 item 1',
              status: 'active'
            },
            {
              title: 'group 1 item 2',
              status: 'inactive'
            }
          ]
        },
        {
          title: 'menu group 2',
          menuItems: [
            {
              title: 'group 2 item 1',
              status: 'active'
            },
            {
              title: 'group 2 item 2',
              status: 'inactive'
            },
            {
              title: 'group 2 item 3',
              status: 'active'
            }
          ]
        }
      ]
    };

What you have to do is create formgroups for each of the menuItems and add them to FormArray. Then you have to create FormGroups for each of the menuGroup and add them to a single FormArray. At the end if you get the value of the whole form group ist should look like this.

{
  "title": "Test Role name",
  "menuGroups": [
    {
      "title": "menu group 1",
      "items": [
        {
          "group 1 item 1": null,
          "group 1 item 2": null
        }
      ]
    },
    {
      "title": "menu group 2",
      "items": [
        {
          "group 2 item 1": null,
          "group 2 item 2": null,
          "group 2 item 3": null
        }
      ]
    }
  ]
}

Create three methods like this.

private buildForm(): void {
    const formArray = this.fb.array([]);
    this.form = this.fb.group({
      title: [this.role.roleName],
      menuGroups: formArray
    });
    this.role.menuGroup.forEach((menuGroup: MenuGroup) => {
      formArray.push(this.buildSubFormGroup(menuGroup))
    });

  }

  private buildSubFormGroup(menuGroup: MenuGroup): FormGroup {
    return this.fb.group({
      title: [menuGroup.title, Validators.required],
      items: this.buildMenuItemFormGroup(menuGroup.menuItems)
    });
  }

  private buildMenuItemFormGroup(menuItems: MenuItem[]): FormArray {
    const formArray = this.fb.array([]);
    const formGroup = this.fb.group({});
    menuItems.forEach((menuItem: MenuItem) => {
      formGroup.addControl(menuItem.title, new FormControl());
    });
    formArray.push(formGroup);
    return formArray;
  }

And go this article to get a clear idea. And Use this stackblitz to see how to create form groups and formArrays.