I have a nested form where users can dynamically add/remove rows from a form. In my form, I have a field called someTypes where I needed to make a customizable dropdown option so I've opted for a mat-menu. When the user clicks on the field, it opens a menu with 2 radio buttons. Selecting the first radio button, populates the form with a value. If the user selects the second radio button, it opens a sub menu that displays a list of options with checkboxes where any of the checkboxes checked, will add their values to the form field's value. So only radio button 1 and the checkboxes will save values, radio button 2 is only used to open the sub menu. The code provided works. The form field control is bound to the checkboxes and radio button, however I had to use an input to display the selected values when the menu closes. The issue I have is that mat-error will not work on the input since it's tied to the checkboxes and the red border on the form field will also not work on the input since it's not technically part of the form. Is there a way to get mat-error and the same visual effects of an invalid form field to be displayed on the input without making a placeholder form field? Specifically what I'd want is the user selects option2, loses focus on the form field and then trigger the validation error parentForm: FormGroup = this.formBuilder.group({ childrenForms: this.formBuilder.array([ this.formBuilder.group({ someTypes: this.formBuilder.array( [], [Validators.required, nonEmptyArrayValidator()], ), }), ]), }); template: <div [formGroup]="rootForm"> @let childrenForms = rootForm | formArray: 'childrenForms'; <ng-container formArrayName="childrenForms"> <ng-container *ngFor="let childForm of childrenForms?.controls; let i = index" [formGroupName]="i"> <div> <p>Form #{{ i + 1 }}</p> </div> <div> <div> @let someTypesForms = childForm | formArray: 'someTypesForms'; <mat-form-field appearance="outline" floatLabel="always"> <mat-label>Some Types</mat-label> <input matInput [matMenuTriggerFor]="menu" placeholder="Select type" [value]="someTypesForms?.value | getTypeDisplayLabel : someList" readonly /> <mat-hint class="mat-error" *ngIf="someTypesForms?.hasError('arrayIsEmpty')">Error Message</mat-hint> </mat-form-field> <mat-menu #menu="matMenu"> <div> <mat-radio-button value="option1" color="primary" (click)="onRadioSelection('option1', i)" (click)="$event.stopPropagation()" (keypress)="onRadioSelection('option1', i)">Option 1</mat-radio-button> </div> <mat-divider></mat-divider> <div> <mat-radio-button (click)="onRadioSelection('option2', i)" (click)="$event.stopPropagation()" (keypress)="onRadioSelection('option2', i);$event.stopPropagation();" value="option2" color="primary">Option 2</mat-radio-button> </div> @if (someTypesForms?.value | isMultiChoice) { @for (option of someList; track option.at(0)) { <mat-checkbox class="checkbox-list" [formControl]="someTypesForms! | getTypeControl : option[0]" (change)="onCheckboxChange($event, i, option[0])" (click)="$event.stopPropagation()" color="primary" (keypress)="$event.stopPropagation()"> <span>{{ option[1].name }}</span> - <span>Some Date: {{ option[1].certDate | formatDate }}</span> </mat-checkbox> } } </mat-menu> </div> </ng-container> </ng-container> </div> controller: onRadioSelection(type: 'option1' | 'option2', index: number) { const someTypeFormArray = this.formArray .at(index) .get('someTypes') as FormArray; someTypeFormArray.clear(); if (type === 'option1') { someTypeFormArray.push(this.formBuilder.control('option1')); } else { someTypeFormArray.push(this.formBuilder.control([])); someTypeFormArray.setErrors({ 'arrayIsEmpty': true }); someTypeFormArray.markAsDirty(); } } Continue reading...