Using custom date formats for Angular Material Date Picker

| By Maina Wycliffe | | | Angular

Angular material has a very nice date picker but while its functionality can accommodate a lot of developers, sometimes it just falls short. For instance, I find it very inflexible when dealing with date formats. While I understand that it’s nice to have a common date format for the whole application, sometimes you need to be able to set date formats on the fly without breaking your back. Sometimes all you need is a simple solution that is ready to be used anywhere in your application.

Introduction

This tutorial assumes you have some knowledge in Angular and Angular Material, because I won’t go into details on the basics like setting up modules. You can learn more about Angular here and Angular Material here. This tutorial has been tested with Angular 6, but I expect it to work with Angular 5 as well but not any earlier version than that.

We will be using ControlValueAccessor from @angular/forms to create a custom form component that will wrap around Angular Material Date Picker component. The new component will extend the Material Date Picker component and allow you to pass a date format in which to use. To format the date, we will use MomentJS which you can learn more about here. Feel free to use a different library or rely with JavaScript/Typescript in build methods.

In the demo for this tutorial, we will have multiple Date Pickers that give back different date formats. To simplify this tutorial, I will ignore all properties of Angular Material Date Pickerthat are optional like minimum and maximum date. This can easily be remedied by passing them as options in your component using the Input() method. This method allows parent components to pass variables to child component, you can learn more about this here.

You can play with this tutorial demo here.

Getting Started

To get started, you need to install (using either NPM or Yarn) the following packages: momentjs, angular-material, angular-flex-layout and material-moment-adapter inside your angular application. You can install them using Yarn in one command as shown below:

yarn add –dev @angular/material moment @angular/material-moment-adapter @angular/flex-layout

For those using Angular 6, you can install angular material using the new ng new command:

ng add @angular/material

Finally import the following in your main NgModules file:

FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
MatDatepickerModule,
MatInputModule,
MatFormFieldModule,
FlexLayoutModule,
MatCardModule

On top of Angular Material, I am using Angular Flex Layout, which you can learn more about here.

Create Custom Date Picker Component

Next, create a new component – date-picker-component – using Angular CLI.

ng new component date-picker

This component will have our Material Date Picker inside it but will read and format the date as we want. It will also accept date input incase we have an initial date or are setting it programmatically from an API. Inside the component typescript file, we are going to implement ControlValueAccessor:

export class DatePickerComponent implements ControlValueAccessor {}

Then, we are going to add a provider for the component, as shown below:

providers: [
  {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => DatePickerComponent), //Name of our component
    multi: true
  }
];

NB: Remember to import remember the necessary imports for the component as shown below:

import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
import * as moment from 'moment';

Inside our component, we need to add a get and set method for the value of the date. We start by declaring a property of the form _dateValue (note the preceding underscore) and then creating the two methods to set and get the value of the _dateValue property:

@Input() _dateValue: string = null;

get dateValue() {
    return moment(this._dateValue, this.format);
}

set dateValue(val) {
    this._dateValue = moment(val).format(this.format);
    this.propagateChange(this._dateValue);
}

On top of those two methods, you need the following methods – which I won’t go into details about:

addEvent(type: string, event: MatDatepickerInputEvent<Date>) {
    this.dateValue = moment(event.value, this.format);
}

writeValue(value: any) {
    if (value !== undefined) {
      this.dateValue = moment(value, this.format);
    }
}

propagateChange = (_: any) => {};

registerOnChange(fn) {
    this.propagateChange = fn;
}

registerOnTouched() {}

We also need a placeholder and format property in our component. The placeholder will be passed to the Material Date Picker Component as a placeholder text. While format property will be used to format the value of the Date Picker when getting.

@Input() public placeholder: string = null;
@Input() private format = 'YYYY/MM/DD HH:mm:ss';

And finally, to our component template, where we will add a normal Material Date Picker input field:

<mat-form-field fxFlex="100">
  <mat-datepicker-toggle matPrefix [for]="picker"></mat-datepicker-toggle>
  <input
    matInput
    [matDatepicker]="picker"
    [value]="dateValue"
    (dateInput)="addEvent('input', $event)"
    [placeholder]="placeholder"
  />
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

And that’s it, you have now a custom date picker that you can use anywhere in your application:

<app-date-picker
  placeholder="Enter The First Date"
  [(ngModel)]="firstDate"
  format="YYYY/MM/DD HH:mm:ss"
></app-date-picker>

You can find the above code on github, here is the link. If you have any questions, please leave it on the comment section below.

Angular 6 - Angular CLI Workspaces

One of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular developers …

Read More
Angular Material Icons Components with Angular 5

Icons are a necessity when building modern-day web apps and sometimes they can be frustrating. While icon sets like Font Awesome and …

Read More
Responsive Navbar with Angular Flex Layout

Today, we are going to create a responsive Navbar using Toolbar and Sidenav Components from Angular Material together with Angular Flex …

Read More
What I learned when I switched to Angular Material from Bootstrap

A couple months ago, I was having a debate on whether I should switch from Bootstrap to Angular Material. I have used Bootstrap for a very …

Read More
Is Angular Flex Layout (with Angular Material) Better than Bootstrap for Responsive Layout?

First before I can say anything else, I want to express my huge respect and love for Bootstrap. I am not writing this to bash bootstrap in …

Read More
Automate Deployment of Angular Apps using AWS CodeBuild

Building and deploying Angular app is very time consuming, especially with large application. You also must keep track of which branch you …

Read More

Comments