I am receiving an object from the db that contains a few elements with the following format:
info = [{ idcentro: "8227", namecentro: "Centro Paris", address: "C/ Paris, 127", dias: [ { dia: "0", horafinal: "06:00", horainicio: "17:00", salas: [ { id: 0, nombre: "sala 1", intervalos: [ ["09:00", "12:30", "10"], ["13:00", "21:30", "20"] ] } ] }, { dia: "1", horafinal: "09:00", horainicio: "16:30", salas: [ { id: 0, nombre: "sala 1", intervalos: [ ["09:00", "12:30", "10"] ] }, { id: 1, nombre: "sala 2", intervalos: [ ["09:00", "20:30", "20"] ] } ] }, { dia: "2", horafinal: "09:00", horainicio: "20:30", salas: [ { id: 0, nombre: "sala 1", intervalos: [ ["09:00", "12:30", "10"], ["12:45", "18:30", "15"] ] }, { id: 1, nombre: "sala 2", intervalos: [ ["09:00", "20:30", "20"] ] } ] } ] }];
To work with those “dias” array and include inputs to modify each value in case the user wants to, I’ve manually created a FormGroup containing a formControl for each of those days (the real object contains up to 8 days).
this.openingHoursForm = new FormGroup({ day0OpeningTime: new FormControl(""), day0ClosingTime: new FormControl(""), day1OpeningTime: new FormControl(""), day1ClosingTime: new FormControl(""), day2OpeningTime: new FormControl(""), day2ClosingTime: new FormControl(""), day3OpeningTime: new FormControl(""), day3ClosingTime: new FormControl(""), day4OpeningTime: new FormControl(""), day4ClosingTime: new FormControl(""), day5OpeningTime: new FormControl(""), day5ClosingTime: new FormControl(""), day6OpeningTime: new FormControl(""), day6ClosingTime: new FormControl(""), day7OpeningTime: new FormControl(""), day7ClosingTime: new FormControl(""), day8OpeningTime: new FormControl(""), day8ClosingTime: new FormControl("") });
And then, in the HTML, I am creating two inputs for each of those those formControlNames:
<div class="dayOpeningHours" title=""> <div>Day 0</div> <div class="opens"> <label for="">De: <input class="form-control" type="time" formControlName="day0OpeningTime" name="day0OpeningTime"> </label> </div> <div class="closes"> <label for="">A: <input class="form-control" formControlName="day0ClosingTime" name="day0ClosingTime"> </label> </div> </div>
As you can see, this is becoming very unmaintainable. I have tried to create the markup (in the html) and formControlNames (in the ts) dynamically by looping through each “dia” of the ‘dias’ array, but I haven’t achieved anything.
Is there a way I can generate the HTML and the declaration of those Form Controls inside the same formGroup? I have been reading about FormArray and AbstractControl but I can not really understand how to apply that to my code.
Can someone help me out or give me some tips to find the right documentation?
Thank you
Advertisement
Answer
The better option would be to use a FormArray
instead. You can also inject FormBuilder
from @angular/forms
See Below
constructor (private fb: FormBuilder) { } diasForm = this.fb.group({ openingHours: this.fb.array([]) }) get openingHours (): FormArray { return this.diasForm.get('openingHours') as FormArray; }
The next task will be to create the form
Lets assume we have dias
as an array
dias = [ { dia: "0", horafinal: "06:00", horainicio: "17:00", }, { dia: "1", horafinal: "06:00", horainicio: "17:00", }, ... ]
I have removed other properties for simplicity
In the ngOnInit
we can set the value of our form
ngOnInit() { this.dias.forEach(dia => { this.openingHours.push( this.fb.group({ horafinal: [dia.horafinal, []], horainicio: [dia.horainicio, []] }) ) }) }
In the Html
<form [formGroup]='diasForm'> <div formArrayName='openingHours'> <div *ngFor='let item of openingHours.controls; let i = index' [formGroupName]='i'> <input formControlName='horafinal' /> <input formControlName='horainicio' /> </div> </div> </form>
The above should match the structure of our formGroup
diasForm( [formGroup] ) ---> openingHours(formArray) ---> i ( [formGroup] ) ---> horafinal(formControl)
Please see this demo on stackblitz
This way you can have a dynamic number of days