htmlangularangular-materialangular-reactive-formsangular-standalone-components

Why doesn't the form display the datepicker?


I'm trying to display a form that consists of two fields: input and datepicker. However, the datepicker doesn't display. Instead, I see the following error message in the console:

ERROR RuntimeError: NG05100: Providers from the BrowserModule have already been loaded. If you need access to common directives such as NgIf and NgFor import the CommonModule instead.

Please help me display both fields of the form:

@Component({
  selector: 'app-root',
  imports: [
    CommonModule,
    BrowserAnimationsModule,
    ReactiveFormsModule,
    FormsModule,
    MatInputModule,
    MatIconModule,
    MatButtonModule,
    MatDatepickerModule,
    MatFormFieldModule,
    MatDatepickerModule,
    MatNativeDateModule,
  ],
  providers: [
    MatDatepickerModule,
    {
      provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
      useValue: {
        appearance: 'outline',
      },
    },
  ],
  template: `
    <div [formGroup]="form">
      <mat-form-field>
        <input matInput type="text" formControlName="f1">
      </mat-form-field>

      <mat-form-field>
        <input 
            matInput 
            [matDatepicker]="p1" 
            formControlName="f2">
        <mat-datepicker-toggle matIconSuffix [for]="p1"></mat-datepicker-toggle>
        <mat-datepicker #p1></mat-datepicker>
      </mat-form-field>
    </div>
  `,
})
export class App {
  formBuilder = inject(FormBuilder);

  form = this.formBuilder.group({
    f1: ['', [Validators.required, Validators.pattern(/^\d{2}$/)]],
    f2: [null, Validators.required],
  });
}

Live DEMO is here


Solution

  • You need to import only what is actually needed, since I do not see any directives of CommonModule, I removed it.

    We need not import BrowserModule or BrowserAnimationsModule ( replaced by provideAnimations() ) when working with Angular Standalone Methodology. So the final code will be.

    bootstrapApplication(App, {
      providers: [provideAnimations()], // provides the animations
    });
    

    And the component only needs the below imports:

    @Component({
      selector: 'app-root',
      imports: [
        ReactiveFormsModule,
        FormsModule,
        MatInputModule,
        MatIconModule,
        MatButtonModule,
        MatDatepickerModule,
        MatFormFieldModule,
        MatDatepickerModule,
        MatNativeDateModule,
      ],
      ...
    

    Full Code:

    import { Component, inject, OnInit } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import {
      FormBuilder,
      FormsModule,
      ReactiveFormsModule,
      Validators,
    } from '@angular/forms';
    import { provideAnimations } from '@angular/platform-browser/animations';
    
    import { MatInputModule } from '@angular/material/input';
    import { MatIconModule } from '@angular/material/icon';
    import { MatButtonModule } from '@angular/material/button';
    import { MatDatepickerModule } from '@angular/material/datepicker';
    import {
      MAT_FORM_FIELD_DEFAULT_OPTIONS,
      MatFormFieldModule,
    } from '@angular/material/form-field';
    import { MatNativeDateModule } from '@angular/material/core';
    
    @Component({
      selector: 'app-root',
      imports: [
        ReactiveFormsModule,
        FormsModule,
        MatInputModule,
        MatIconModule,
        MatButtonModule,
        MatDatepickerModule,
        MatFormFieldModule,
        MatDatepickerModule,
        MatNativeDateModule,
      ],
      providers: [
        MatDatepickerModule,
        {
          provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
          useValue: {
            appearance: 'outline',
          },
        },
      ],
      template: `
      
    <div [formGroup]="form">
      <mat-form-field>
        <input matInput type="text" formControlName="f1">
      </mat-form-field>
    
      <mat-form-field>
        <input 
            matInput 
            [matDatepicker]="p1" 
            formControlName="f2">
        <mat-datepicker-toggle matIconSuffix [for]="p1"></mat-datepicker-toggle>
        <mat-datepicker #p1></mat-datepicker>
      </mat-form-field>
    </div>
      `,
    })
    export class App implements OnInit {
      formBuilder = inject(FormBuilder);
    
      form = this.formBuilder.group({
        f1: ['', [Validators.required, Validators.pattern(/^\d{2}$/)]],
        f2: [null, Validators.required],
      });
    
      ngOnInit() {
        console.log(this.form);
      }
    }
    
        bootstrapApplication(App, {
          providers: [provideAnimations()],
        });
    
    

    Stackblitz Demo