Reputation: 19
I want to know the efficient appraoch in terms of handling a form with multiple tabs in angular.
For example I have a form with mat-group and three tabs such as business hours / out of office and holiday.
I have three fields which are present in all those three tabs such as title, calendar and colour.
Apart from that calendar / colour are present in a separate div.
Here is some part of the html file of the form with some formControlName.
Note : The following html form with three mat-tabs are working fine and I have added just for the referene.
<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">
<!--START OF THE =>>>>>>>>>>>>>>>>>>>>>>>>>>Business Hours MAT TAB <<<<<<<<<<<<<<<<<<<<<<<<<<<<<= -->
<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>
<!-- Start of the SHIFTSSSSSSSSSSSSSSSSSSSSS section in the event variable form group -->
<div formArrayName="shifts" class="shift-main">
<div *ngFor="let shift of shifts.controls; let i = index" [formGroupName]="i" class="shift-info">
<mat-label>Shifts</mat-label>
<mat-form-field class="shift-title" [color]="underLineColor">
<input matInput type="text" class="shift-value" formControlName="shift">
</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>
<button mat-raised-button class="shift-btn" (click)="addShift()">Add Shift</button>
</div>
<!-- Recurrence Event Section in the Business Hours. -->
<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)"
formControlName="recurrenceCriteria" [(ngModel)]="repeatOption">
<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 label="Out of Office">
<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="datepicker-section time-selection event-fields">
<mat-icon>access_time</mat-icon>
<mat-label>Date & time</mat-label>
<mat-form-field [color]="underLineColor">
<!-- <mat-label>Choose a date</mat-label> -->
<input formControlName="datePicker" matInput [matDatepicker]="picker5" [min]="yesterday" (click)="picker5.open()">
<mat-datepicker #picker5></mat-datepicker>
</mat-form-field>
<mat-form-field appearance="fill" class="time-select-value time-from" *ngIf="!allDayEvent">
<mat-select [(value)]="selectedTimeFrom" [disabled]="allDayEvent">
<mat-option *ngFor="let timeFrom of selectTime" [value]="timeFrom.value">
{{timeFrom.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill" class="time-select-value" *ngIf="!allDayEvent">
<mat-select [(value)]="selectedTimeFrom">
<mat-option *ngFor="let timeTo of selectTime" [value]="timeTo.value">
{{timeTo.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field [color]="underLineColor" class="pl-2 time-to" *ngIf="allDayEvent">
<!-- <mat-label>Choose a date</mat-label> -->
<input formControlName="datePicker" matInput [matDatepicker]="picker6" [min]="eventForm.controls['datePicker'].value" (click)="picker6.open()">
<mat-datepicker #picker6></mat-datepicker>
</mat-form-field>
<div class="clearfix"></div>
<mat-checkbox formControlName="allDayEvent" [(ngModel)]="allDayEvent">All Day</mat-checkbox>
</div>
<div class="message-section event-fields">
<div class="form-group p-0">
<mat-label class="p-0">Message</mat-label>
<mat-form-field [color]="underLineColor" appearance="fill">
<input matInput formControlName="timeMessage" placeholder="Enter Message">
</mat-form-field>
</div>
<!-- <div class="add-shift col-md-2 offset-md-9">
<button mat-raised-button class="shift-btn">Add Shift</button>
</div> -->
</div>
<div class="recurrence-section event-fields {{repeatOption == 'custom' ? 'repeat-custom-option':''}}">
<mat-icon>replay</mat-icon>
<mat-label>Repeat</mat-label>
<mat-form-field appearance="fill">
<!-- <mat-label>Choose a date</mat-label>-->
<mat-select #selectRepeatOptions (selectionChange)="recurrence($event, customRecurrence)"
formControlName="recurrenceCriteria" [(ngModel)]="repeatOption">
<mat-option *ngFor="let option of recurrenceOptions" [value]="option">
{{option | titlecase}}</mat-option>
</mat-select>
</mat-form-field>
<span class="repeat-custom-value" *ngIf="repeatOption == 'custom'" (click)=selectRepeatOptions.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="date-range-section event-fields" *ngIf="eventForm.controls['recurrenceCriteria'].value === 'does not repeat' ">
<!-- <img src="/assets/images/check_outline.svg" alt="done">-->
<mat-icon>check_circle_outline</mat-icon>
<mat-label class="p-0">Expiry Date</mat-label>
<mat-form-field appearance="fill">
<mat-date-range-input [rangePicker]="picker1">
<input matStartDate formControlName="dateRangeStart" matInput placeholder="Start date">
<input matEndDate formControlName="dateRangeEnd" matInput placeholder="End date">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
<mat-date-range-picker #picker1></mat-date-range-picker>
</mat-form-field>
</div>
</div>
</mat-tab>
<mat-tab label="Holiday">
<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="message-section event-fields">
<div class="form-group p-0">
<mat-label class="p-0">Message</mat-label>
<mat-form-field [color]="underLineColor" appearance="fill">
<input matInput formControlName="timeMessage" placeholder="Enter Message">
</mat-form-field>
</div>
</div>
<div class="recurrence-section event-fields {{repeatOption == 'custom' ? 'repeat-custom-option':''}}">
<mat-icon>replay</mat-icon>
<mat-label>Repeat</mat-label>
<mat-form-field appearance="fill">
<!-- <mat-label>Choose a date</mat-label>-->
<mat-select #selectRepeatHoliday (selectionChange)="recurrence($event, customRecurrence)"
formControlName="recurrenceCriteria" [(ngModel)]="repeatOption">
<mat-option *ngFor="let option of recurrenceOptions" [value]="option">
{{option | titlecase}}</mat-option>
</mat-select>
</mat-form-field>
<span class="repeat-custom-value" *ngIf="repeatOption == 'custom'" (click)=selectRepeatHoliday.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="date-range-section event-fields">
<mat-icon>access_time</mat-icon>
<mat-label>Expiry Date</mat-label>
<!-- <img src="/assets/images/check_outline.svg" alt="done"> -->
<mat-form-field appearance="fill">
<mat-date-range-input [rangePicker]="picker2">
<input matStartDate formControlName="dateRangeStart" matInput [min]="yesterday" placeholder="Start date">
<input matEndDate formControlName="dateRangeEnd" matInput [min]="yesterday" placeholder="End date">
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
<mat-date-range-picker #picker2></mat-date-range-picker>
</mat-form-field>
</div>
</div>
</mat-tab>
</mat-tab-group>
<div class="select-calendar-section">
<!-- <img src="/assets/images/calendar.svg" alt="cal">-->
<mat-icon>today</mat-icon>
<!-- <div class=""> -->
<mat-label>Select Calender</mat-label>
<mat-form-field appearance="fill">
<mat-select formControlName="calendars" [(ngModel)]="selectedCalendar" [(value)]="selectedCalendar">
<mat-option *ngFor="let calendar of calendarList" [value]="calendar.name" >
{{calendar?.name}}</mat-option>
</mat-select>
</mat-form-field>
<!-- </div> -->
<!-- <div class=""> -->
<mat-form-field #colorMenuTrigger="matMenuTrigger" [matMenuTriggerFor]="colorPicker"
style="margin-left: 2.125rem;" appearance="fill">
<mat-select [ngStyle]="{'background':selectedColor}" class="color-select" formControlName="color">
</mat-select>
</mat-form-field>
<!-- </div> -->
</div>
<div class="template-action row">
<div class="col-md-12">
<div class="form-action-area">
<button mat-raised-button (click)="onClose()" class="gray-btn">Cancel</button>
<button mat-raised-button [disabled]="!eventForm.valid" (click)="onEventSave()" [mat-dialog-close]="true"
class="blue-btn service-trigger">{{saveBtnText}}</button>
</div>
</div>
</div>
</form>
</div>
</div>
</ng-template>
That is the complete form that I have attached and only for the reference I have attached it.
And here is the from initiliazation ,
this.eventForm = this.fb.group({
title: ["Title", [Validators.required]],
datePicker: [""],
shifts: this.fb.array([]),
endDate: [""],
calendars: ["", [Validators.required]],
color: [""],
endDateCriteria: ["never"],
recurrenceCriteria: ["does not repeat"],
timeMessage: [""],
allDayEvent: false,
// dateRange: this.fb.group({
dateRangeStart: [""],
dateRangeEnd: [""],
recurrenceRule: [""]
});
The event From contains all these formControls in it.
Problem Is stated below.
Now real issue arrises whenI click on the create button and that event contains all the values of the event Form. How can I handle tabs efficiently.
First solution that comes to my mind is that , I extract the values from the from on the basis of the tabIndex and adjust the payload and send it to the backend for saving it.
onEventSave() {
if(this.activeTabIndex === 0) {
const formData = this.eventForm.value;
console.log("this is the first tab index")
console.log("Here is on submit now",this.eventForm.value);
} else if(this.activeTabIndex === 1) {
console.log("this is the second tab index")
} else if(this.activeTabIndex === 2) {
console.log("this is the third tab index")
}
}
This is how I can handle all the events and save it in the databasis and add the field in it of eventType in the payload. Is this an efficient apprach. ?
If I use it then how I will handle the update case as when i click on the event on a calendar then how I will go to the respective tab form and patch values. ?
If I need to use any other way to handle such calendar app then how would I get the values of colour and calendar that are being used in a separate div? It will be duplicate code if i put it in every mat-tab and use it. Right ?
Or I need to handle tabs in a different and efficient way. Let me know please and you can review the html file code where I can do it better.
Suggenstion / Articles related to it / Demos. All are welcome.
I want to handle three tabs in angular reactive forms differently and extract the values from the tab and process it further efficiently.
How can I create different events such as Out of office / business hours / holiday events with a sinlge button of create in a form and extract the values form the respective tab and process it further. And how can I handle the update case.
Thanks.
Upvotes: 0
Views: 466
Reputation: 862
One solution might be to create child group inside your eventForm
.
Then depending on the tab selected you only send the group related to the tab.
this.eventForm = this.fb.group({
businessHoursGroup: this.fb.group({...}),
shiftHoursGroup: this.fb.group({...}),
...
});
Upvotes: 0