Search code examples
angularangular-materialdatepickermat-datepicker

Failing to setup mat-datepicker in angular component


Migrating an application from ng 15 (I think) to 18. I'm having a headache with a date picker component. I've removed my implementation (with bindings) and replaced with one from a tutorial (angular university).

I keep hitting "ERROR TypeError: i is null". If I remove any reference to mat-datepicker in my template, I don't get that error.

So I suspect it's something about my component/project setup and importing stuff incorrectly.

In part of my efforts to migrate to ng 18 I ended up adding stuff to main.ts (might have even added the file), I've ended up with module imports in there as well as the component, which I suspect my not be needed.

So 3 questions:

  • What is best way to track down an error that doesn't see very descriptive to me (I understand null vars, but no indication what is null)?
  • What am I doing wrong with my date-picker setup?
  • Do I need both imports in component AND module imports in main.ts?

My component.ts:

@Component({
    selector: 'app-edit',
    templateUrl: './edit.component.html',
    styleUrls: ['./edit.component.scss'],
    standalone: true,
    imports: [MatFormField, MatHint, MatLabel, MatInput, FormsModule,
              MatDatepicker, MatDatepickerInput, MatDatepickerToggle,
              MatSuffix,
              MatTabGroup, MatTab, NgFor, ExaminerComponent, RefereeComponent, MatButton]
})
export class MyComponent implements OnInit {@Component({
    selector: 'app-component',
    templateUrl: './my.component.html',
    styleUrls: ['./my.component.scss'],
    standalone: true,
    imports: [MatFormField, MatHint, MatLabel, MatInput, FormsModule, MatDatepicker, MatDatepickerInput, MatDatepickerToggle, MatSuffix, MatTabGroup, MatTab, NgFor, MatButton]
})
export class myComponent implements OnInit {
.. removed for brevity ..
}

Component.html:

<mat-form-field>
  <mat-label>Choose a date</mat-label>
  <input matInput [matDatepicker]="picker">
  <mat-hint>MM/DD/YYYY</mat-hint>
  <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

Main.ts

bootstrapApplication(AppComponent, {
  providers: [
    appConfig.providers,
    [provideExperimentalZonelessChangeDetection()],
    importProvidersFrom(
      FormsModule,
      FontAwesomeModule,
      ReactiveFormsModule,
      MatDatepickerModule,
      MatToolbarModule,
      MatSnackBarModule,
      MatCardModule,
      MatButtonModule,
      MatIconModule,
      MatTabsModule,
      MatMenuModule,
      LoggerModule.forRoot({level: !environment.production ? NgxLoggerLevel.DEBUG : NgxLoggerLevel.OFF})),
    {provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: {duration: 50000}},
    {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
    {provide: MAT_DATE_FORMATS, useValue: DATE_FORMATS},
    {provide: MAT_DATE_LOCALE, useValue: 'en-GB'},
    provideHttpClient(withInterceptorsFromDi()),
    provideAnimations()
  ]
})
  .catch(err => console.error(err));

Solution

  • Please add the below line in your app.component.ts:

    providers: [provideNativeDateAdapter()]
    

    app.components.ts

    import { Component } from '@angular/core';
    import { MatButtonModule } from '@angular/material/button';
    import { RouterOutlet } from '@angular/router';
    
    import { MatDatepickerModule } from '@angular/material/datepicker';
    import { MatInputModule } from '@angular/material/input';
    import { MatFormFieldModule } from '@angular/material/form-field';
    import { provideNativeDateAdapter } from '@angular/material/core';
    @Component({
      selector: 'app-root',
      standalone: true,
      providers: [provideNativeDateAdapter()],
      imports: [MatFormFieldModule, MatInputModule, MatDatepickerModule],
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss'] // Ensure this path is correct
    })
    export class AppComponent {
    
    }