10

I have a problem about set array value to formBuilder.array. In the formBuilder that not array it can use this way to setValue but in formBuilder.array I can't do it. I try set value to formbuilder 'listServiceFeature' and 'listservicefeature' but it's not set value either way.

ts

listServiceFeature: any = ['m1', 'm2']

contentFormValidate(): void {

  this.contentForm = this.formBuilder.group({
          'listservicefeature': this.formBuilder.array([
              this.formBuilder.group({
                 listServiceFeature: ['', [Validators.required]
              });
          ]),
  });

  this.contentForm.controls['listservicefeature'].setValue(this.listServiceFeature);
}


addServiceFeature() {
    const control = <FormArray>this.contentForm.controls['listservicefeature'];
    control.push(this.initServiceFeature());
}

removeServiceFeature(i: number) {
    const control = <FormArray>this.contentForm.controls['listservicefeature'];
    control.removeAt(i);
}

html

<div formArrayName="listservicefeature">
  <div class="form-group" *ngFor="let servicefeature of contentForm.controls.listservicefeature.controls; let i=index">
    <label for="Service">Features {{i+1}}</label>
    <div class="input-group" [formGroupName]="i">
        <input type="text" class="form-control" formControlName="listServiceFeature">
        <template [ngIf]="i == 0">
            <span class="input-group-btn">
            <button (click)="addServiceFeature()" class="btn btn-default" type="button">
            <span class="lnr lnr-plus-circle icon-orange-gable-buttom"></span>
            </button>
            </span>
        </template>
        <template [ngIf]="i > 0">
            <span class="input-group-btn">
            <button (click)="removeServiceFeature(i)" class="btn btn-default" type="button">
            <span class="lnr lnr-trash icon-orange-gable-buttom"></span>
            </button>
            </span>
        </template>
    </div>
  </div>
</div>

2 Answers 2

10

Angular 6 FormBuilder array Example

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
           <app-team></app-team>
          `
})
export class AppComponent {
} 

employee.ts

export class Employee {
    empId = '';
    empName = ''; 
    skill = '';
} 

department.ts

export class Department {
    deptHead = ''; 
    deptName = '';
} 

team.ts

import { Employee } from './employee';
import { Department } from './department';

export class Team {
    teamName = '';
        teamManager = '';   
    teamDept : Department;
    employees: Employee[];
} 

team-data.ts

import { Team } from './team';

export const ALL_TEAMS: Team[] = [
 {
  "teamName":"Java Team",
  "teamManager":"Yogi",
  "teamDept":{
     "deptHead":"Modi",
     "deptName":"M Commerce"
   },
   "employees":[
      {
        "empId":"101",
        "empName":"Harish",
        "skill":"Java"
      },
      {
        "empId":"111",
        "empName":"Mohit",
        "skill":"Angular"
      }
     ]
  } 
];

export const ALL_SKILLS = [
   {name: 'Java', displayName: 'Java'},
   {name: 'Angular', displayName: 'Angular'},
   {name: 'Dot Net', displayName: 'Dot Net'}
]; 

team-management.service.ts

import { Injectable } from '@angular/core';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';

import { Team } from './team';
import { ALL_TEAMS, ALL_SKILLS } from './team-data';

@Injectable()
export class TeamManagementService { 
        getSkills() {
        return Observable.of(ALL_SKILLS);       
    }
    getAllTeams(): Observable<Team[]> {
        return Observable.of(ALL_TEAMS);
    }
    getTeamByName(name: string): Observable<Team> {
            return this.getAllTeams()
             .map(allTeams => allTeams.find(team => team.teamName === name));
        }
        saveTeam(team: Team) {
        console.log('------------TEAM------------');
        console.log('Team Name: '+ team.teamName);
        console.log('Team Manager: '+ team.teamManager);
        console.log('Dept Head: '+ team.teamDept.deptHead);
        console.log('Dept Name: '+ team.teamDept.deptName);
        console.log('----- Employee Detail -----');
        for(let emp of team.employees) {
            console.log('Emp Id: '+ emp.empId);
            console.log('Emp Name: '+ emp.empName);
            console.log('Emp Skill: '+ emp.skill);      
                        console.log('-------------------');         
        }
    }       
} 

team-management.component.ts

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, FormArray, Validators, FormBuilder } from '@angular/forms';
import { Observable } from 'rxjs/Observable';

import { TeamManagementService } from './team-management.service';
import { Team } from './team';
import { Employee } from './employee';
import { Department } from './department';

@Component({
  selector: 'app-team', 
  templateUrl: './team-management.component.html'
})
export class TeamManagementComponent implements OnInit {
  teamForm:FormGroup;
  formSubmitted = false;
  allSkills: Observable<any[]>
  constructor(
          private formBuilder:FormBuilder,
          private teamMngService: TeamManagementService) { 
  }
  ngOnInit() {
      this.allSkills = this.teamMngService.getSkills();
      this.createTeamForm();
      this.addEmployee();
  }
  createTeamForm(){
      this.teamForm = this.formBuilder.group({
         teamName: ['', Validators.required ],
         teamManager: '',
         teamDept: this.formBuilder.group(new Department()),
             employees: this.formBuilder.array([]) 
      }); 
  }
  get empFormArray(): FormArray{
      return this.teamForm.get('employees') as FormArray;
  }
  addEmployee(){
      let fg = this.formBuilder.group(new Employee());
      this.empFormArray.push(fg);     
  }
  deleteEmployee(idx: number) {
      this.empFormArray.removeAt(idx);
  }
  loadTeam(name: string) {
      this.teamMngService.getTeamByName(name)
         .subscribe( team => {
            this.createFormWithDefaultData(team);
         });
  }  
  createFormWithDefaultData(team: Team) {
      //this.teamForm.patchValue(team);       
      this.teamForm.patchValue({
        teamName: team.teamName,
        teamManager: team.teamManager,
        teamDept: team.teamDept
      }); 
      let employeeFormGroups = team.employees.map(employee => this.formBuilder.group(employee));
          let employeeFormArray = this.formBuilder.array(employeeFormGroups);
          this.teamForm.setControl('employees', employeeFormArray);
  }
  onFormSubmit() {
          let data = JSON.stringify(this.teamForm.value);
      console.log('-----Team in JSON Format-----');
      console.log(data);
      let team: Team = this.teamForm.value;
      this.teamMngService.saveTeam(team);
      this.formSubmitted = true;
      this.teamForm.reset();      
  }  
  resetTeamForm() {
      this.teamForm.reset({
          teamName: 'Java Team',
          teamManager: 'Yogi'
      });
  }
} 

team-management.component.html

<h3>Create New Team 
  <button type="button" (click)="loadTeam('Java Team')" > Load Default Team </button>
  <button type="button" (click)="resetTeamForm()"> Reset </button>
</h3>
<div *ngIf="formSubmitted && teamForm.pristine" class = "submitted"> Form submitted successfully. </div>
<div class="team">
 <form [formGroup]="teamForm" (ngSubmit)="onFormSubmit()">
   <p>Team Name : <input formControlName="teamName">
     <br/><label *ngIf="teamForm.get('teamName').invalid && teamForm.get('teamName').dirty" class = "error"> Team name is required. </label>
   </p>
   <p>Team Manager : <input formControlName="teamManager"></p>

   <b>Department :</b><br>
   <div formGroupName="teamDept" class="department"> 
     <p>Department Head : <input formControlName="deptHead"></p>
     <p>Department Name : <input formControlName="deptName"></p>
   </div>
   <div class="all-emp">
     <b> Employees in Team :</b><br><br>
     <div formArrayName="employees"> 
          <div *ngFor = "let emp of empFormArray.controls; let idx = index" [formGroupName]="idx" class="employee">
          <p> <b>Employee : {{idx + 1}}</b> </p>
              <p>Emp Id : <input formControlName="empId"></p>
          <p>Emp Name : <input formControlName="empName"></p>
          <p>Skill :
          <select formControlName="skill">
            <option *ngFor="let skill of allSkills | async" [ngValue]="skill.name">
                 {{ skill.displayName }}
            </option>
              </select>
          </p>  
          <p><button type="button" (click)="deleteEmployee(idx)">Delete</button></p>
      </div>
     </div>
     <button type="button" (click)="addEmployee()">Add More Employee</button>
   </div> <br/>
   <button [disabled]="teamForm.invalid">SUBMIT</button>
 </form>
</div> 

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule }    from '@angular/forms'; 

import { AppComponent }  from './app.component';
import { TeamManagementComponent }  from './team-management.component';
import { TeamManagementService }  from './team-management.service';

@NgModule({
  imports: [     
        BrowserModule,
    ReactiveFormsModule
  ],
  declarations: [
        AppComponent,
    TeamManagementComponent
  ],
  providers: [ 
        TeamManagementService
  ],  
  bootstrap: [
        AppComponent
  ]
})
export class AppModule { } 

styles.css

.employee {
    border: 2px solid blue;
    width: 275px;
}
.department {
    border: 2px solid blue;
    width: 275px;
}
.team {
    border: 3px solid black;
    width: 300px;
}
.all-emp {
    border: 3px solid black;
    width: 275px;   
}
.error{
        color: red;
} 
.submitted{
        color: green;
        font-size: 20px;
} 
Sign up to request clarification or add additional context in comments.

Comments

2

It looks to me like what you want to do is to add a control to the formArray. Take a look at the documentation for reactive-forms

https://angular.io/guide/reactive-forms

quote:

Notice that you replace the previous FormArray with the FormGroup.setControl method, not with setValue. You're replacing a control, not the value of a control.

in the documentation they do like this: 1) Add a getter as shortcut to the formArray:

 get listservicefeatures(): FormArray {
    return this.contentform.get('listservicefeature') as FormArray;
  };

2) create an add method that would look like this:

addServiceFeature()  {
this.listservicefeatures.push(this.fb.group({newservicefeature: 'defaultvalue', [Validators.required]}));
}

also your inital declaration of the formArray should probably look like this:

this.contentForm = this.formBuilder.group({
          'listservicefeature': this.formBuilder.array([]),
  });

I hope this helps :)

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.