3

I have a project using Angular 5 at the moment and I am new to this angular concept.

I have a component where user can choose which module they want to use ... module has interface like:

export interface ModuleComponent{
    id: number;
    moduleName: string;
    level: number;
    parentId: number;
    displayOrder: number;
    children: ModuleComponent[];
}

It self referencing object parent and children. In here I just want the user to access the children modulecomponents ... not parrent.

my form.component.ts like this :

import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder, FormArray } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { AlertifyService } from './../../_services/alertify.service';
import { UserGroup } from './../../_models/usergroup';
import { ModuleComponent } from './../../_models/moduleComponent';
import { UserGroupService } from './../../_services/userGroup.service';
import { environment} from './../../../environments/environment';

@Component({
  selector: 'app-form-usergroup',
  templateUrl: './form-usergroup.component.html',
  styleUrls: ['./form-usergroup.component.css']
})
export class FormUserGroupComponent implements OnInit {
    @Input() ug: UserGroup;
    @Input() moduleComponents: ModuleComponent[];
    @Input() buttonName: string; 
    @Output() onSubmit = new EventEmitter<any>();
    editForm: FormGroup;

  constructor(private ugService: UserGroupService,
    private fb: FormBuilder,
    private route: ActivatedRoute,
    private router: Router,
    private alertify: AlertifyService) { 


    }

  ngOnInit() {
      this.createForm();
  }

  createForm() {
      this.editForm = this.fb.group({
          groupName: [this.ug.groupName, Validators.required],
          details : this.fb.array([])
      });

      this.setDetails(this.moduleComponents);
  }

  get details(): FormArray {
      return this.editForm.get('details') as FormArray ;
  }


  setDetails(details: ModuleComponent[]) {
    let arr = [] ; 
    details.forEach(dt => {
        if(dt.children){
            dt.children.forEach(x => {
                let fc = new FormControl();
                if(this.ug.details.includes(x.id))
                {
                    fc.setValue(true);
                }
                arr.push(fc);
            });
        }
    });
    const arrFR = this.fb.array(arr);
    this.editForm.setControl('details', arrFR);
  }
}

with input from parent component have data like this:

this.ug = {
 'groupName' : 'Module List'
 'details': [1,2,3,4,7,9,10] ; // these are id of selected modules  
}

Now my html like:

import {
  Component,
  OnInit,
  Input,
  EventEmitter,
  Output
} from '@angular/core';
import {
  FormGroup,
  FormControl,
  Validators,
  FormBuilder,
  FormArray
} from '@angular/forms';
import {
  Router,
  ActivatedRoute
} from '@angular/router';
import {
  AlertifyService
} from './../../_services/alertify.service';
import {
  UserGroup
} from './../../_models/usergroup';
import {
  ModuleComponent
} from './../../_models/moduleComponent';
import {
  UserGroupService
} from './../../_services/userGroup.service';
import {
  environment
} from './../../../environments/environment';

@Component({
  selector: 'app-form-usergroup',
  templateUrl: './form-usergroup.component.html',
  styleUrls: ['./form-usergroup.component.css']
})
export class FormUserGroupComponent implements OnInit {
  @Input() ug: UserGroup;
  @Input() moduleComponents: ModuleComponent[];
  @Input() buttonName: string;
  @Output() onSubmit = new EventEmitter < any > ();
  editForm: FormGroup;

  constructor(private ugService: UserGroupService,
    private fb: FormBuilder,
    private route: ActivatedRoute,
    private router: Router,
    private alertify: AlertifyService) {


  }

  ngOnInit() {
    this.createForm();
  }

  createForm() {
    this.editForm = this.fb.group({
      groupName: [this.ug.groupName, Validators.required],
      details: this.fb.array([])
    });

    this.setDetails(this.moduleComponents);
  }

  get details(): FormArray {
    return this.editForm.get('details') as FormArray;
  }


  setDetails(details: ModuleComponent[]) {
    let arr = [];
    details.forEach(dt => {
      if (dt.children) {
        dt.children.forEach(x => {
          let fc = new FormControl();
          if (this.ug.details.includes(x.id)) {
            fc.setValue(true);
          }
          arr.push(fc);
        });
      }
    });
    const arrFR = this.fb.array(arr);
    this.editForm.setControl('details', arrFR);
  }

}
<div class="container">
  <div class="row">
    <form [formGroup]="editForm" class="form-horizontal">
      <div class="panel panel-info">
        <div class="panel-heading">
          <h3 class="panel-title">User Group</h3>
        </div>
        <div class="panel-body">
          <div class="form-group required" [ngClass]="{'has-error': editForm.get('groupName').touched && editForm.get('groupName').hasError('required')}">
            <label for="groupName" class="col-sm-2">User Group Name</label>
            <div class="col-sm-7">
              <input type="text" class="form-control" placeholder="Group Name" formControlName="groupName">
              <span class="help-block" *ngIf="editForm.get('groupName').touched && editForm.get('groupName').hasError('required')">Group Name is required</span>
            </div>
          </div>
          <div class="panel-body">
            <tabset>
              <tab *ngFor="let mod of moduleComponents" heading="{{mod.moduleName}}">
                <div class="row">
                  <div class="col-sm-4" *ngFor="let child of mod.children; let i = index">
                    <input type="checkbox"> {{child.moduleName}} {{child.id}}
                  </div>
                </div>
              </tab>
            </tabset>
          </div>
        </div>
      </div>
    </form>
  </div>
</div>

As you can see I still haven't put the FormArray into my html, I still have no idea how to put the FormControl for checkboxes. Please tell me how to do that.

Let me explain further, I wish I could have this :

okay I will explain the logic behind that code and what I was expected. In php / plain html I wish I could create many checkboxes like this

<input type="checkbox" name="details[]" value="1"> Module 1
<input type="checkbox" name="details[]" value="2"> Module 2
<input type="checkbox" name="details[]" value="3"> Module 3
<input type="checkbox" name="details[]" value="4"> Module 4 
.......
<input type="checkbox" name="details[]" value="20"> Module 20

so when submitted it will return details[1,2,5,6] => where checkbox checked.

2
  • I think I cannot have the answer for this problem. so I created "manual" value populating for the checkboxes. Commented Jun 27, 2018 at 11:05
  • Solutions I use: codepen.io/anon/pen/VdEMvQ Commented Jun 27, 2018 at 11:05

2 Answers 2

1

I do not know the logic you are trying to implement inside the setDetails function, but as per my understanding, below is the logic to add controls to formArray and initialize the same with values and put validators if required be:

setDetails(details: ModuleComponent[]) {
    let arr = [] ; 
    details.forEach(dt => {
        if(dt.children){
            dt.children.forEach(x => {
                this.editForm.controls['details'].push(this.fb.group({
                 'id': [x.id, Validaors.required],
                  'pass': [x.pass, Validaors.required]
             }))
            });
        }
    });

  }

Hope I could help ? Let me know if I could help further.

Sign up to request clarification or add additional context in comments.

2 Comments

I just edited my question & explained in the last line. Thank you.
there seems to be a similar issue raised. Please visit the below link:stackoverflow.com/questions/40927167/…
1

i think you need declare formgroup on your html for your checkbox controls, something like this (not sure if you need formArray or formGroup):

<div class="panel-body" formArrayName="details">

or

<div class="panel-body" formGroupName="details">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.