angularangular-reactive-formsdynamic-forms

I want to display a dynamic form only when there are values for that id as below?How can i approach it?


enter image description hereI have object coming from backend,like this template_parameter: "namespace,resources", and for some ids it is template_parameter: "null". When there are some values in the template_parameter: "namespace,resources", I wanted to display a form with those fileds. if it is null, i dont want to display, How can I approach this.I split values, But i am trying to write a code which only displays a form when it there are some values. Hope you understand my question. appreciate your help. Thank you. Html:

<form [formGroup]="templateform">

    <div class="form-group">
        <label for="ntw-pol-egren-podns"  class="bmd-label-floating">{{variable1}}<sup
        class="text-danger">*</sup>
        </label>
        
        <input  [(ngModel)]="namespace" formControlName="namespace" type="text" class="form-control" id="ntw-pol-egren-podns">
        
        <div *ngIf="submitted && f.namespace.errors" class="error-feedback error">
            <p *ngIf="f.namespace.errors.required" class="text-danger">
                Namespace is required
            </p>
        </div>
    </div>
    
    <div class="form-group">
        <label for="ntw-pol-egren-podns" class="bmd-label-floating">{{variable2}}<sup
        class="text-danger">*</sup></label>
        
        <input type="text" class="form-control" formControlName="resource" [(ngModel)]="resources"  id="ntw-pol-egren-podns">
        <div *ngIf="submitted && f.resource.errors" class="error-feedback error">
            <p *ngIf="f.resource.errors.required" class="text-danger ">
                Resource is required
            </p>
        </div>
    </div>
    
    <div class="d-flex justify-content-end">
        <button  (click)="sendclusteridApi()"  class="btn btn-primary px-3 py-2">Save</button>
    </div>
</form>

ts:

changeSelection() {
    this.selectedItemsList = this.DisplayProductList.filter((product, index) => {
        this.selectedItemsList.push(this.DisplayProductList[index])
        console.log(this.selectedItemsList,"sel")
        let splitstring = this.DisplayProductList[index].template_parameter
        console.log(splitstring,"df")
        let sepratedArray = splitstring.split(',');
        this.variable1 = sepratedArray[0];
        this.variable2 = sepratedArray[1];
        return product.isChecked;
    });
}

Solution

  • Create FormGroup :

     productFG: FormGroup;
    

    Iterate through your array of this.DisplayProductList and create FormGroup for each Entry

    const productFArray = this.DisplayProductList.map(obj =>
      this.createFormGroup(obj)
    );
    
    this.productFG = this.fb.group({
      policies: this.fb.array(productFArray)
    });
    

    creating FormGroup, dynamically create a control for Id, label and for template_parameter we will create nested FormGroup named additionalParams

    private createFormGroup(obj): FormGroup {
        return this.fb.group({
          id: [obj.id],
          label: [obj.label],
          additionalParams: this.formGroupByTemplate(obj.template_parameter)
        });
      }
    
      private formGroupByTemplate(template_parameter: string): FormGroup {
        const splitted = template_parameter.split(',');
        if (template_parameter == '') {
          return this.fb.group({});
        } else {
          const formGroup = this.fb.group({});
          splitted.forEach(val => formGroup.addControl(val, this.fb.control(null)));
          return formGroup;
        }
      }
    

    Other helper getters

      get policiesFormArray(): FormArray {
        return this.productFG.get('policies') as FormArray;
      }
    
      getGroup(index: number): FormGroup {
        return this.policiesFormArray.at(index) as FormGroup;
      }
    
      getTemplateFG(index: number): FormGroup {
        return this.getGroup(index).get('additionalParams') as FormGroup;
      }
    
      getFormGroupKeys(index): string[] {
        return Object.keys(this.getTemplateFG(index).controls);
      }
    

    In template : Used getFormGroupKeys to retrive formControlName from the additionalParams FormGroup.

    <form [formGroup]="productFG">
      <div formArrayName="policies">
        <div *ngFor="let control of policiesFormArray.controls; let i=index">
          <div [formGroupName]="i">
            <div> {{ "Id : "+ getGroup(i).get('id').value }} - {{ getGroup(i).get('label').value }} </div>
            <div formGroupName="additionalParams" *ngFor="let key of getFormGroupKeys(i);">
              {{ key }} : <input type="text" [formControlName]="key"><br><br>
            </div>
          </div>
    
        </div>
      </div>
    
    </form>
    

    Demo