Thank you for reading my blog posts, I am no longer publishing new content on this platform. You can find my latest content on either mainawycliffe.dev or All Things Typescript Newsletter (✉️)
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.
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.
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.
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.
One of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular developers …
Read MoreIcons are a necessity when building modern-day web apps and sometimes they can be frustrating. While icon sets like Font Awesome and …
Read MoreToday, we are going to create a responsive Navbar using Toolbar and Sidenav Components from Angular Material together with Angular Flex …
Read MoreA 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 MoreFirst 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 MoreBuilding and deploying Angular app is very time consuming, especially with large application. You also must keep track of which branch you …
Read More