Is it correct to implement a custom NgbDateParserFormatter to change the format of the input value on NgbInputDatepicker?

28,752

Solution 1

As of today implementing a custom NgbDateParserFormatter is the best way to go. So yes, it is a correct way.

In the future we might have a more sophisticated implementation of the NgbDateParserFormatter where you will be able to just pass a desired format (ex. yyyy-MM-dd). Adding this feature will depend on user's interest.

You might also check some more background info in https://github.com/ng-bootstrap/ng-bootstrap/issues/754#issuecomment-247767027

Solution 2

Create custom parser formatter.

import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { Injectable } from '@angular/core';

@Injectable()
export class NgbDateCustomParserFormatter extends NgbDateParserFormatter {

  format(date: NgbDateStruct): string {
    return date ? `${isNumber(date.day) ? padNumber(date.day) : ''}-${isNumber(date.month) ? padNumber(date.month) : ''}-${date.year}` : '';
  }
}

Set the provider for the custom parser formatter in the @NgModule.

providers: [
    {provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter}
]

As described in the api

Share:
28,752
Nelson Lopez Centeno
Author by

Nelson Lopez Centeno

Updated on July 22, 2022

Comments

  • Nelson Lopez Centeno
    Nelson Lopez Centeno almost 2 years

    I'm using the datepicker (ng-boostrap) in a popup and I would like to change the date format to dd-mm-yyyy.

    It seems that it can be solved by implementing a new NgbDateParserFormatter to replace the default NgbDateISOParserFormatter.

    But I was wondering if there is another way.

    UPDATE:

    A small implementation of NgbDateParserFormatter using Moment.js (tested with version 1.0.0-alpha.14 of ng-bootstrap):

    import {NgbDateParserFormatter, NgbDateStruct} from '@ng-bootstrap/ng-bootstrap';
    import * as moment from 'moment';
    
    export class NgbDateMomentParserFormatter extends NgbDateParserFormatter {
        constructor(private momentFormat: string) {
            super();
        };
        format(date: NgbDateStruct): string {
            if (date === null) {
                return '';
            }
            let d = moment({ year: date.year, 
                             month: date.month - 1, 
                             date: date.day });
            return d.isValid() ? d.format(this.momentFormat) : '';
        }
    
        parse(value: string): NgbDateStruct {
            if (!value) {
                return null;
            }
            let d = moment(value, this.momentFormat);
            return d.isValid() ? { year: d.year(), 
                                   month: d.month() + 1, 
                                   day: d.date() } : null;
        }
    }
    

    And in a module, you include the provider using a factory to indicate the date format as a parameter:

    ---
    
    @NgModule({
    
      ---
    
      providers: [
        { 
          provide: NgbDateParserFormatter, 
          useFactory: () => { return new NgbDateMomentParserFormatter("DD-MM-YYYY") } 
        }
      ]
    
      ---
    
    })
    
    • David
      David over 7 years
      Be aware - moment expects to have zero indexed months. Your code fails on every day of december.
    • Nelson Lopez Centeno
      Nelson Lopez Centeno over 7 years
      Thanks @David, I fixed the code. When I posted the code, NgbDateStruct was using zero indexed months too, but that changed later.
    • Mohan Ram
      Mohan Ram about 7 years
      @Nelson I tried your approach. I have added providers in the core module of my application to change date format of my date picker component. Its not working. Help me out.
    • Nelson Lopez Centeno
      Nelson Lopez Centeno about 7 years
      @MohanRam Could you share your code?
    • HammerNL
      HammerNL over 6 years
      Note that, in a more recent Angular 4 version, useFactory on providers no longer exists. Use: useValue: new NgbDateMomentParserFormatter("DD-MM-YYYY") instead
    • Alejandro
      Alejandro about 4 years
      as of today, this still works with @HammerNL's fix. Thanks!
    • Gustavo Amaro
      Gustavo Amaro almost 4 years
      Your update content worked perfectly for me! Thanks!
  • Daimz
    Daimz over 7 years
    I am also wondering how I can change the formate on the dates, would it be possible to add a simple example of how to implement the NgbDateParserFormatter without moment.js I simply want to be able to reformat the date.
  • murk003
    murk003 about 7 years
    @pkozlowski.opensource How should this answer be changed if we are using AOT compilation? I have tried export function NgbDateMomentParserFormatterFactory() { return new NgbDateMomentParserFormatter("DD-MM-YYYY"); } and providers: [ { provide: NgbDateParserFormatter, useFactory: NgbDateMomentParserFormatterFactory }] but that doesn't seem to apply the changes.
  • sgotre
    sgotre almost 7 years
    Do not use a factory when using AOT Compiler. Try this example:gist.github.com/nrobinaubertin/61ff1c3db355c74f4e56f‌​485b566ab22
  • HaneTV
    HaneTV over 5 years
    Although it works on a clean project, it didn't work for my fairly big app (lots of modules importing each others...) with Ng5 and AoT compilation (JiT works but it's not an option for me). Is there an other way to do that ?