The custom native date adapter is facing compatibility issues following the upgrade of Angular/Material from version 5 to 6

In my Angular 5 application, I had implemented a custom date adapter as follows:

import {NativeDateAdapter} from "@angular/material";
import {Injectable} from "@angular/core";

@Injectable()
export class CustomDateAdapter extends NativeDateAdapter {

    parse(value: any): Date | null {
        if ((typeof value === 'string') && (value.indexOf('/') > -1)) {
            const str = value.split('/');
            return new Date(Number(str[2]), Number(str[1])-1, Number(str[0]), 12);
        }
        const timestamp = typeof value === 'number' ? value : Date.parse(value);
        return isNaN(timestamp) ? null : new Date(timestamp);
    }

    format(date: Date, displayFormat: Object): string {
        return date.getFullYear() + "-" + (date.getMonth() + 1).toString().padStart(2, '0') + "-" + date.getDate().toString().padStart(2, '0');
    }

}

This custom date adapter was defined in app.module.ts.

@NgModule({
    imports: [...],
    declarations: [...],
    providers: [
        ...,
        { provide: DateAdapter, useClass: CustomDateAdapter }
    ],
    bootstrap: [
        AppComponent
    ]
})
export class AppModule {}

However, after upgrading to Angular/Material version 6, the custom date adapter stopped working and an error started occurring. The error message is:

ERROR TypeError: Cannot read property 'TRIDENT' of undefined
    at new NativeDateAdapter (native-date-adapter.ts:83)
    at new CustomDateAdapter (custom.date.adapter.ts:5)
    at _createClass (ng_module.ts:171)
    at _createProviderInstance$1 (ng_module.ts:143)
    at resolveNgModuleDep (ng_module.ts:104)
    at NgModuleRef_.get (refs.ts:502)
    at resolveDep (provider.ts:416)
    at createClass (provider.ts:276)
    at createDirectiveInstance (provider.ts:135)
    at createViewNodes (view.ts:303)

I found a solution on Stack Overflow where it was suggested to add a constructor:

constructor(matDateLocale: string) {
    super(matDateLocale, new Platform());
}

After adding this constructor, a new error occurred:

ERROR Error: StaticInjectorError(AppModule)[DateAdapter -> String]: 
  StaticInjectorError(Platform: core)[DateAdapter -> String]: 
    NullInjectorError: No provider for String!
    at NullInjector.get (injector.ts:35)
    at resolveToken (injector.ts:332)
    at tryResolveToken (injector.ts:274)
    at StaticInjector.get (injector.ts:154)
    at resolveToken (injector.ts:332)
    at tryResolveToken (injector.ts:274)
    at StaticInjector.get (injector.ts:154)
    at resolveNgModuleDep (ng_module.ts:124)
    at _createClass (ng_module.ts:173)
    at _createProviderInstance$1 (ng_module.ts:143)

At this point, I am seeking suggestions on how to resolve this issue and make the custom date adapter work again.

Answer №1

I successfully resolved the issue by implementing the MomentDateAdapter along with a customized date format.

import {NgModule} from "@angular/core";
import {AppComponent} from "./app.component";
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from "@angular/material";
import {MomentModule} from "ngx-moment";
import {MomentDateAdapter} from '@angular/material-moment-adapter';

export const ISO_FORMAT = {
    parse: {
        dateInput: 'LL',
    },
    display: {
        dateInput: 'YYYY-MM-DD',
        monthYearLabel: 'MMM YYYY',
        dateA11yLabel: 'LL',
        monthYearA11yLabel: 'MMMM YYYY',
    },
};

@NgModule({
    imports: [
        MomentModule,
        ...
    ],
    declarations: [
        AppComponent,
        ...
    ],
    providers: [
        {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
        {provide: MAT_DATE_FORMATS, useValue: ISO_FORMAT},
        ...
    ],
    bootstrap: [
        AppComponent
    ]
})

export class AppModule {}

Answer №2

Make sure not to rely on moment and instead refer to the official documentation.

Here is a straightforward example of using a customized date adapter.

Customized date adapter:

import { Platform } from '@angular/cdk/platform';
import { DatePipe } from '@angular/common';
import { Inject, Injectable, Optional } from '@angular/core';
import { MAT_DATE_LOCALE, NativeDateAdapter } from '@angular/material/core';

@Injectable()
export class CustomDateAdapter extends NativeDateAdapter {
  constructor(@Optional() @Inject(MAT_DATE_LOCALE) matDateLocale: string, platform: Platform) {
    super(matDateLocale, platform);
  }

  format(date: Date): string {
    // implement custom logic here
    return new DatePipe(this.locale).transform(date, 'MMMM YYYY');
  }
}

How to use in your component:

import { Platform } from '@angular/cdk/platform';
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MatDatepicker } from '@angular/material/datepicker';
import { CustomDateAdapter } from './CustomDateAdapter';

export const MY_FORMATS = {
  parse: {
    dateInput: 'MMMM YYYY',
  },
  display: {
    dateInput: 'MMMM YYYY',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

@Component({
  selector: 'app-month-picker',
  templateUrl: './month-picker.component.html',
  styleUrls: ['./month-picker.component.scss'],
  providers: [
    {
      provide: DateAdapter,
      useClass: CustomDateAdapter,
      deps: [MAT_DATE_LOCALE, Platform],
    },
    { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
  ],
})
export class YourComponent

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The condition in a Typescript function that checks for strings will never evaluate to true

I encountered a strange issue with a TypeScript condition in a function. Here is my current code, where the parameters are passed from outside: getLevel(validation: string, status: string): string { let card = ""; if (validation == &qu ...

Unexpected Null Object Error in TypeScript Function

Hi there! I'm new to TypeScript and encountered an 'Object may be null' error in a function. The function is meant to add two LinkedLists together, each representing numbers (with each digit as its own node), and return a new LinkedList. Can ...

Combining class and data within an iteration while utilizing ngFor

I have a dynamic table with rows generated using ngFor <tbody> <tr *ngFor="let item of Details"> <div class="row details-row row-cols-lg-2 row-cols-1" *ngIf="closureDetails"> <div ...

Retrieve a specific element from an array list

Hey everyone, I'm facing a problem in my application where I need to extract a specific value from my array and display it in a table for users to see. Check out the code snippet below: Here's my mock data: { "Data": "2020-0 ...

Error: The type '{ children: Element[]; className: string; }' cannot be assigned to the type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'

My current setup involves using Next.js and TypeScript While working in Visual Studio Code, I encountered an error message stating Type error: Type '{ children: Element[]; className: string; }' is not assignable to type 'DetailedHTMLProps&l ...

Unidirectional data flow from the document object model to the variable within the

When working with Angular, there are multiple methods available for binding variables to DOM properties. You can utilize the `{{}}` syntax, `[property]=expression`, or implement two-way ngModel binding. One aspect that I have not yet discovered is how to ...

Arranging React Grid Items with Stylish Overlapping Layout

Is there a way to create a react-grid-layout with 100 grid points width, while ensuring that the grid items do not overlap? (Reducing the number of columns can prevent overlap, but sacrifices the 100-point width resolution for grid placement) import Butto ...

Error encountered during Jasmine unit testing for the ng-redux @select directive

Here is a snippet from my component.ts file: import { Component, OnInit } from '@angular/core'; import { select } from 'ng2-redux'; import { Observable } from 'rxjs/Observable'; import { PersonalDetailsComponent } from ' ...

Trigger event when ngModel changes

Currently, I am trying to perform a test on a select element... <select [ngModel]="selectedRouters" name="routerName" class="form-control" id="routersSelect" size="12" (ngModelChange)="selectRouters($event)" multiple> <option [value]="route ...

Angular app experiences a breakdown due to a JitCompiler issue

After being given the responsibility of enhancing a project, I diligently added new modules and components. However, upon running the application, it crashes. Uncaught Error: Component EnquiryComponent is not part of any NgModule or the module has not bee ...

Whoops! Looks like there was a hiccup with the Vercel Deployment Edge Function, causing an

Every time I attempt to send a POST request to my Edge Function on Vercel Deployment, I encounter the following error message: [POST] /api/openai reason=EDGE_FUNCTION_INVOCATION_FAILED, status=500, user_error=true TypeError: Illegal invocation at app/api/ ...

Exploring Next.js 13: Enhancing Security with HTTP Cookie Authentication

I'm currently working on a web app using Next.js version 13.4.7. I am setting up authentication with JWT tokens from the backend (Laravel) and attempting to store them in http-only cookies. Within a file named cookie.ts, which contains helper functio ...

What advantages does using an RxJS Subject have over handling multiple event listeners individually in terms of speed

After investigating a page's slow performance, I identified an angular directive as the root cause. The culprit was a piece of code that registered event listeners on the window keydown event multiple times: @HostListener('window:keydown', ...

The dropdown menus in Bootstrap are expanding outside the screen when opened

When I click on the dropdown in the Navbar on the right side, the menus open up far to the right and are not visible until I scroll horizontally. Here is the code snippet: <nav class="navbar navbar-expand-lg navbar-light bg-light"> < ...

Issue: subscribe function is not definedDescription: There seems to be an

I'm currently trying to retrieve a value from an array based on a specific element, and then finding the exact matching element. Unfortunately, I've encountered an error with this.getProduct(name1: string) function even though I have already impo ...

`Warning: The alert function is not working properly in the console error

I am currently working on integrating otp functionality into my Ionic 3 project. I am facing an issue where I am able to receive the otp, but it is not redirecting to the otp receive page due to a specific error. Below is the console error that I am encou ...

Angular2/4 is throwing a 405 error, indicating that the method used is not

updateEmployeeData(ename,ejobtitle,edept,eunit,equal,eaqser,empid) { let url = GlobalVariable.BASE_API_URL + "api/updateEmployeeProfile"; let headers = new Headers({'Content-Type':'application/json'}); let options = new Reque ...

Having trouble loading extensive amounts of data into a select element within an Angular application

Upon successfully retrieving around 14000 data entries from an HTTP request, I am facing difficulties loading this vast amount of data into my Select Tag. This is causing the entire page to slow down. The structure of the select Tag in question is as follo ...

Implementing a GIF loader in your webpack configuration for a Typescript/React/Next.js application

Upon inserting a .gif file in my Typescript React app, an error message has surfaced. ./src/gif/moving.gif 1:6 Module parse failed: Unexpected token (1:6) You may need an appropriate loader to handle this file type, currently no loaders are configured to p ...

Leveraging Angular for Remote Configuration Management

How is everything going with you? I'm attempting to retrieve a configuration that I previously set up in Firebase's remote config using my Angular 15 application. The specific configuration is called "AllowedUsers." Here is the image of th ...