Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a custom component on top of Angular Material mat-select

I want to create a custom component on top of angular material mat-select. The custom component should support both reactive form and not a reactive form.

The custom component get inputs as:
@Input() group: FormGroup; @Input() controlName: string;

the custom component HTML

<mat-form-field [formGroup]="group">
  <mat-select placeholder="Favorite food" [formControlName]="controlName">
    <mat-option *ngFor="let food of foods" [value]="food.value">
      {{food.viewValue}}
    </mat-option>
  </mat-select>
</mat-form-field>

it works fine when I pass the group and the controlName but when I want to use the same component without reactive form I get error: "formGroup expects a FormGroup instance. Please pass one in"

<!-- With Reactive Form -->
<app-custom-dropdown [group]="form" [controlName]="'foods'"></app-custom-dropdown>

<!-- Without Reactive Form -->
<app-custom-dropdown></app-custom-dropdown>

My Question is how I can support both cases when the custom component used with reactive form and in other time without reactive form.

stackblitz Example

like image 347
ofir fridman Avatar asked Feb 04 '26 14:02

ofir fridman


1 Answers

when you are using template form and calling your component like so

<app-custom-dropdown></app-custom-dropdown>

you do not pass formGroup, so in you app-custom-dropdown component @Input() group will be undefined, which you are passing in template

<mat-form-field [formGroup]="group">

so here you need to add condition to not pass group if it's undefined

UPDATE here is one of possible examples

<ng-container *ngTemplateOutlet='group ? reactive : template'>
</ng-container>

<ng-template #reactive>
  <mat-form-field [formGroup]="group">
    <mat-select placeholder="Favorite food" [formControlName]="controlName">
      <mat-option *ngFor="let food of foods" [value]="food.value">
        {{food.viewValue}}
      </mat-option>
    </mat-select>
  </mat-form-field>
</ng-template>

<ng-template #template>
  <mat-form-field>
    <mat-select placeholder="Favorite food" >
      <mat-option *ngFor="let food of foods" [value]="food.value">
        {{food.viewValue}}
      </mat-option>
    </mat-select>
  </mat-form-field>
</ng-template>
like image 119
Artyom Amiryan Avatar answered Feb 06 '26 03:02

Artyom Amiryan