I'm working with Angular Material and moment.js. I had the problem that dates were parsed according to my timezone, instead of just, well, what the user entered.
There's already a question about it here and it also has a working answer. But it's rather old, not taking into account standalone components, which do offer the possibility of providing stuff directly at the component level. However, that does not work in this case:
@Component({
selector: 'app-component-with-material-datepicker',
templateUrl: './component-with-material-datepicker.component.html',
styleUrls: ['./component-with-material-datepicker.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
MatDatepickerModule,
MatMomentDateModule,
],
providers: [
{ provide: ErrorStateMatcher, useClass: InstantErrorStateMatcher }, // works
MomentDateAdapter,
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } }, // no effect
],
})
export class ComponentWithMaterialDatePicker {
// ...
This leaves me no choice but to provide the config at module level. I wish to understand why.
But that provider is an environmentProvider
and they need to be placed in the providers array of bootstrapApplication
second parameter. So could you check the below stackblitz. Where I add in environment providers and it seems to work fine!
Important points:
import
import { provideMomentDateAdapter } from '@angular/material-moment-adapter';
code
bootstrapApplication(App, {
providers: [
importProvidersFrom(MatNativeDateModule),
provideMomentDateAdapter(undefined, { useUtc: true }),
provideAnimations(),
],
});
code
import { Component, importProvidersFrom } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import moment from 'moment';
import { MatNativeDateModule } from '@angular/material/core';
import { provideMomentDateAdapter } from '@angular/material-moment-adapter';
import { provideAnimations } from '@angular/platform-browser/animations';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [
MatFormFieldModule,
MatInputModule,
MatDatepickerModule,
FormsModule,
ReactiveFormsModule,
CommonModule,
],
template: `
<mat-form-field>
<mat-label>Moment.js datepicker</mat-label>
<input matInput [matDatepicker]="dp" [formControl]="date">
<mat-hint>MM/DD/YYYY</mat-hint>
<mat-datepicker-toggle matIconSuffix [for]="dp"></mat-datepicker-toggle>
<mat-datepicker #dp></mat-datepicker>
</mat-form-field>
{{date.value | json}}
`,
})
export class App {
name = 'Angular';
date = new FormControl(moment([2017, 0, 1]));
}
bootstrapApplication(App, {
providers: [
importProvidersFrom(MatNativeDateModule),
provideMomentDateAdapter(undefined, { useUtc: true }),
provideAnimations(),
],
});