Quiero crear un nested form
a partir de datos:
Mis datos reales son:
mainObject = { adminname: 'Saqib', adminemail: 'email@example.com', users: [ { user_type: 'Adult', count: 3 }, { user_type: 'Child', count: 1 }, { user_type: 'infant', count: 0 }, ], };
Quiero mostrar formularios anidados para estos recuentos en la matriz de usuarios. por ejemplo, debería haber 3 formularios para adultos, 1 formulario para niños y ningún formulario para bebés, ya que el recuento de bebés es 0. Y estos recuentos se pueden cambiar como si pudiera haber 0 niños y 1 bebé.
.html
<form [formGroup]="myForm" (ngSubmit)="onSubmit()"> <input formControlName="name" placeholder="Enter Admin Name" /> <br /> <input formControlName="admin_email" placeholder="Enter Admin Email" /> <div formArrayName="users"> <div *ngFor="let pro of myForm.get('users').controls; let i = index"> <br /> <div [formGroupName]="i" style="border: 1px solid; padding: 10px"> <div>User Type: {{ pro.value.user_type }}</div> User Name:<br /> <input type="text" formControlName="user_name" /> <br /> Email:<br /> <input type="text" formControlName="user_email" /> </div> </div> </div> <p> <button type="submit">Submit</button> </p> </form>
.ts
myForm: FormGroup; mainObject = { adminname: 'Saqib', adminemail: 'email@example.com', users: [ { user_type: 'Adult', count: 3 }, { user_type: 'Child', count: 1 }, { user_type: 'infant', count: 0 }, ], }; // I want to Show forms according to this users count with their Type: // according to this data there should be 3 adult forms, 1 hchild form and no infant Form. constructor(private fb: FormBuilder) {} ngOnInit() { this.formInit(); } formInit() { this.myForm = this.fb.group({ name: '', admin_email: '', users: this.fb.array( this.mainObject.users.map((e) => this.newUsers(e.user_type, e.count)) ), }); } get users(): FormArray { return this.myForm.get('users') as FormArray; } newUsers(t, c): FormGroup { console.log(t, c); return this.fb.group({ user_type: t, user_name: '', user_email: '', }); } onSubmit() { console.log(this.myForm.value); }
He creado un ejemplo de Stackblitz para una mejor comprensión:
Quizás puedas lograr el concepto de la siguiente manera:
Concepto:
Cree un diccionario con grupo por clave: user_type
y valor: una matriz con (número de) objeto(s) creado(s) en función del count
.
Obtenga el valor del resultado 1, realice una matriz anidada plana y agregue esos objetos en una matriz.
toFormUsers(users: any[]): any[] { // Generate array by user_type let userTypeGroup = users.reduce((accumulator, current) => { accumulator[current.user_type] = accumulator[current.user_type] || []; for (let i = 0; i < current.count; i++) accumulator[current.user_type].push({ user_type: current.user_type }); return accumulator; }, {}); // Flatten array of array for userTypeGroup return [].concat( ...Object.keys(userTypeGroup).map((x) => userTypeGroup[x]) ); }
Y modifique su FormGroup
para aplicar el método anterior pasando mainObject.users
.
this.myForm = this.fb.group({ name: '', admin_email: '', users: this.fb.array( this.toFormUsers(this.mainObject.users).map((e) => this.newUsers(e.user_type, e.count)) ), });
Para crear una matriz anidada de Count en la matriz de usuarios desde mainObject
:
.ts
ngOnInit() { this.formInit(); } formInit() { this.myForm = this.fb.group({ name: '', admin_email: '', users: this.fb.array([]), }); this.mainObject.users.map((e) => { if (e.count > 0) { for (let i = 0; i < e.count; i++) { this.addUser(e.user_type); } } }); } addUser(t) { const userArray = <FormArray>this.myForm.controls['users']; const newUser = this.initUser(t); userArray.push(newUser); } initUser(t) { return this.fb.group({ user_type: t, user_name: '', user_email: '', }); } get users(): FormArray { return this.myForm.get('users') as FormArray; } newUsers(t, c): FormGroup { console.log(t, c); return this.fb.group({ user_type: t, user_name: '', user_email: '', }); }