I am developing a calendar app and want to handle three tabs such as hours timing / out of office / holiday tabs in a form.
what is the efficient appraoch to group the form as there is one form and three tabs and only one button to create an event.
I am doing it in this way and initializing from in ngOnInit lifecycle hook and I have done it in this way.
this.eventForm = this.fb.group({
businessHours: this.fb.group({
title: ["Title", [Validators.required]],
datePicker: [""],
shifts: this.fb.array([]),
calendars: ["", [Validators.required]],
color: [""],
endDateCriteria: ["never"],
recurrenceCriteria: ["does not repeat"],
dateRangeStart: [""],
dateRangeEnd: [""],
recurrenceRule: [""]
}),
outOfOffice: this.fb.group({
// title: ['', Validators.required],
// Add other controls as needed
}),
holiday: this.fb.group({
// title: ['', Validators.required],
// Add other controls as needed
})
});
This is where I am grouping a form with three different tabs
and in the below snippet I have the .html file code where I want to show the formcontrol. But now the issue here is that I got the error of all the formControls that `core.js:6210 ERROR Error: Cannot find control with name: 'title'`
Similar errors related to other controls.
<ng-template #eventFormVariable>
<div class="dialog-container event-header">
<div class="mat-card-header">
<mat-icon (click)="onClose()">close</mat-icon>
<h4 class="content-span full-width">{{formHeading}}</h4>
</div>
<div class="dialog-content event-dialog">
<form class="form-horizontal form-bordered" [formGroup]="eventForm">
<mat-tab-group animationDuration="0ms" (selectedTabChange)="onTabChanged($event);" [(selectedIndex)]="activeTabIndex">
<mat-tab label="Business Hours">
<div class="col-md-12 p-0">
<div class="title-section event-fields">
<mat-form-field [color]="underLineColor">
<input matInput formControlName="title">
</mat-form-field>
</div>
<div class="shift-section event-fields">
<mat-icon class="time-icon">access_time</mat-icon>
<div class="datepicker-section">
<mat-label>Start Date</mat-label>
<mat-form-field [color]="underLineColor">
<input formControlName="datePicker" matInput [matDatepicker]="picker" [min]="yesterday" (click)="picker.open()">
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</div>
<div formArrayName="shifts">
<div>
<div *ngFor="let shift of shifts.controls; let i = index" [formGroupName]="i" class="shift-main">
<mat-label>Shifts</mat-label>
<mat-form-field class="shift-title" [color]="underLineColor">
<input matInput type="text" class="shift-value" formControlName="shifts">
</mat-form-field>
<mat-form-field [color]="underLineColor">
<span class="time-select-value time-from">
<mat-select formControlName="selectedTimeFrom">
<mat-option *ngFor="let timeFrom of selectTime" [value]="timeFrom.value">
{{timeFrom.viewValue}}
</mat-option>
</mat-select>
</span>
</mat-form-field>
<mat-form-field [color]="underLineColor">
<span class="time-select-value">
<mat-select formControlName="selectedTimeTo">
<mat-option *ngFor="let timeTo of selectTime" [value]="timeTo.value">
{{timeTo.viewValue}}
</mat-option>
</mat-select>
</span>
</mat-form-field>
<button class="remove-btn" mat-icon-button (click)="removeShift(i)">
<mat-icon>close</mat-icon>
</button>
</div>
</div>
</div>
<button mat-raised-button class="shift-btn" (click)="addShift()">Add Shift</button>
</div>
<div class="recurrence-section event-fields" [ngClass]="{ 'repeat-custom-option': repeatOption === 'custom' }">
<mat-icon>replay</mat-icon>
<mat-label>Repeat</mat-label>
<mat-form-field appearance="fill">
<mat-select #selectRepeat (selectionChange)="recurrence($event, customRecurrence)"
[(ngModel)]="repeatOption" [ngModelOptions]="{standalone: true}">
<mat-option *ngFor="let option of recurrenceOptionsForBusiness" [value]="option">
{{ option | titlecase }}
</mat-option>
</mat-select>
</mat-form-field>
<span class="repeat-custom-value" *ngIf="repeatOption === 'custom'" (click)="selectRepeat.open()">
{{ repeatType === 'week' ? 'Weekly on' : repeatType }}
<span class="week-values" *ngIf="repeatType === 'week'">
<span *ngFor="let day of weekDays"> {{ day }} </span>
</span>
</span>
</div>
<div class="end-date-section event-fields {{eventForm.controls['endDateCriteria'].value === 'custom' ? 'repeat-custom-option':''}}" *ngIf="repeatOption !== 'does not repeat'">
<mat-icon>check_circle_outline</mat-icon>
<mat-label>Expiry Date</mat-label>
<mat-form-field appearance="fill">
<mat-select #selectEndDate formControlName="endDateCriteria" [(value)]="selected">
<mat-option value="never">Never</mat-option>
<mat-option value="custom" (click)="openEndDateModal(endDateReference)">Custom</mat-option>
</mat-select>
</mat-form-field>
<span class="repeat-custom-value" *ngIf="eventForm.controls['endDateCriteria'].value === 'custom'" (click)=selectEndDate.open()> {{endDate | date}}
</span>
</div>
</div>
</mat-tab>
</mat-tab-group>
There are other tabs code as well I just have shortened it with respect to the single tab. I just want to know the effiecient appraoch with respect to handling the three tabs in a single form group . what that can be in angluar.
I am finding it difficult to handle three tabs in a single form as getting error related to formControls that these formcontrols are not found but i have used the same formControl and initiliazed it in ngOnInit.
How to efficiently handle the forms with multiple tabs so I can pick the values of the respective tab and process it further as I have a single submit button.
We can use the property preserveContent
to true in mat-tab-group
, which will prevent destroy of the elements when not visible, forms do not work well, when the elements are destroyed, also the elements are grouped under a formGroup (businessHours
) so we need to specify a formGroupName="businessHours"
for each mat-tab
, so that forms will understand to which group the elements belong to!
<div class="dialog-container event-header">
<div class="mat-card-header">
<mat-icon>close</mat-icon>
<h4 class="content-span full-width">{{'formHeading'}}</h4>
</div>
<div class="dialog-content event-dialog">
<form class="form-horizontal form-bordered" [formGroup]="eventForm">
<mat-tab-group
[preserveContent]="true"
animationDuration="0ms"
[(selectedIndex)]="activeTabIndex"
>
<mat-tab label="Business Hours" formGroupName="businessHours">
<div class="col-md-12 p-0">
<div class="title-section event-fields">
<mat-form-field>
<input matInput formControlName="title" />
</mat-form-field>
</div>
</div>
</mat-tab>
</mat-tab-group>
</form>
</div>
</div>
{{eventForm.value | json}}