Override Angular default date pipe
Asked Answered
O

3

14

I need to override the default Angular 7 date pipe formats (medium, short, fullDate, etc.), because I don't want to use two date pipes (the default one and a custom one), so I made the following and was wondering is a good idea to do it like so:

// extend-date.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common';

@Pipe({
  name: 'date'
})
export class ExtendDatePipe extends DatePipe implements PipeTransform {
  constructor() {
    super('en-US');

    this.customDateFormats = {
      medium: '...',
      short: '...',
      fullDate: '...',
      longDate: '...',
      mediumDate: '...',
      shortDate: '...',
      mediumTime: '...',
      shortTime: '...'
    };
  }

  transform(value: any, args?: any): any {
    switch (args) {
      case 'medium':
        return super.transform(value, this.customDateFormats.medium);
      case 'short':
        return super.transform(value, this.customDateFormats.short);
      case 'fullDate':
        return super.transform(value, this.customDateFormats.fullDate);
      case 'longDate':
        return super.transform(value, this.customDateFormats.longDate);
      case 'mediumDate':
        return super.transform(value, this.customDateFormats.mediumDate);
      case 'shortDate':
        return super.transform(value, this.customDateFormats.shortDate);
      case 'mediumTime':
        return super.transform(value, this.customDateFormats.mediumTime);
      case 'shortTime':
        return super.transform(value, this.customDateFormats.shortTime);
      default:
        return super.transform(value, args);
    }
  }
}

// app.component.html
{{ someDate | date: 'medium' }} // The custom format will be displayed

If I use something like {{ someDate | date: 'MM/dd/yyyy' }} it works as well.

So basically, I'm wondering is there a case where this will not work properly or maybe there is a better way to achieve this, but with different implementation?

Openhearth answered 7/5, 2019 at 10:22 Comment(2)
you can use momentjs for this: momentjs.comRounce
It's a good idea. Using inheritance to do it is pretty clean, too.Agminate
J
15

You are missing out on some functionality from the date pipe. It has besides format, also timezone and locale as parameters.

Overriding a default pipe is possible, where the one which is added 'last' will get priority. To override an angular pipe throughout the app, it's enough to add your custom pipe to the declarations array of your root AppModule:

@NgModule({
  //...
  declarations: [
    //...
    ExtendDatePipe 
  ]
})
export class AppModule {}

note: there used to be a PLATFORM_PIPES constant to override global/default pipes, but this has been removed

For readability and to keep localization and i18n possibilities, I would just change it to this though.:

@Pipe({
  name: 'date'
})
export class ExtendDatePipe extends DatePipe implements PipeTransform {
  readonly customFormats = {
    medium: 'xxx',
    short: 'xxx',
    // ...
  };
  
  constructor(@Inject(LOCALE_ID) locale: string) {
    super(locale);
  }

  transform(value: any, format = 'mediumDate', timezone?: string, locale?: string): string {
    format = this.customFormats[format] || format;
    
    return super.transform(value, format, timezone, locale);
  }
}
Jackjackadandy answered 7/5, 2019 at 10:33 Comment(3)
How did you came to the "pipes" property inside the NgModule config? The property did not exist on my app. However simply adding this custom pipes to "declarations" did the trick.Pulvinate
@PieterDeBie that's a big booboo on my end :) you are absolutely right, it needs to be declarations! Thanks for the heads upJackjackadandy
It's not working in Angular 12 anymore, I tried the solution of github.com/angular/angular/issues/39691 but it's not overriding anythingHeptagonal
A
9

Since Angular 15, you can override the default date pipe config (format, timezone, etc.) using the DATE_PIPE_DEFAULT_OPTIONS injection token. It works like this in your app.module.ts:

providers: [
  {provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {dateFormat: 'mm/DD/yy'}}
]

Official documentation

Agminate answered 5/1, 2023 at 22:31 Comment(0)
C
0

The bests solutions have be explained in the past answers. Just only for information, is possible override multiple predefined formats of angular:

import {
  FormatWidth,
  registerLocaleData,
} from '@angular/common';
import {
  ɵLocaleDataIndex,
} from '@angular/core';
import locale from '@angular/common/locales/{yourLocale}';

const dateFormats = locale[ɵLocaleDataIndex.DateFormat] as string[];

/**
 * Override/replace "mediumDate" with the format "shortDate", consequently
 * changing "medium" as well.
 */
dateFormats[FormatWidth.Medium] = dateFormats[FormatWidth.Short];

/**
 * Override/replace "shortDate" with the format "MM/yyyy", consequently
 * changing "short" as well.
 */
dateFormats[FormatWidth.Short] = 'MM/yyyy';

registerLocaleData(locale);

Howover, can be broken easily by angular next updates if implementation is changed.

Cummerbund answered 28/7, 2023 at 21:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.