1

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.

1 Answer 1

1

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}}

Stackblitz Demo

Sign up to request clarification or add additional context in comments.

1 Comment

yes. It worked well as I missed the part of mentioning the formGroup in the mat-tab group.

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.