Angular Material is ground running with significant, modern UI components that work across the web, mobile, and desktop.
Angular Material components will help us construct attractive UI and UX, consistent and functional web pages, and web applications while keeping to modern web design principles like browser portability and compatibility, device independence, and graceful degradation.
Angular Datepicker
Angular Datepicker is a built-in material component that allows us to enter the date through text input or by choosing the date from a calendar. Angular Material Datepicker allows users to enter the date through text input or by choosing the date from the calendar. The Material Datepicker comprises several components and directives that work together.
It is made up of various angular components and directives that work together. First, we need to install Angular. We are using Angular CLI to install the Angular.
Step 1: Install the Angular CLI.
Type the following command.
npm install -g @angular/cli
Now, create the Angular project using the following command.
ng new datepicker
Step 2: Install other libraries.
Go into the project and install the hammerjs using the following command.
npm install --save hammerjs
Hammer.js is the optional dependency and helps with touch support for a few components.
Now, install Angular Material and Angular Animations using the following command.
npm install --save @angular/material @angular/animations @angular/cdk
Now, include hammerjs inside the angular.json file. You can find this file at the root of the project.
Step 3: Import a pre-built theme and Material icons.
Angular Material comes with some pre-built themes. These themes have set off the colors and basic styling.
The main available themes are indigo-pink, deeppurple-amber, purple-green, and pink-bluegrey.
To import the theme, you can add the following code to your global styles.css file. The file is inside the src folder.
@import '~@angular/material/prebuilt-themes/indigo-pink.css';
You can also access the Material Design icons and use named icons with a <mat-icon> component.
If we want to import them to your project, we can add this to the head section of your project’s root index.html file.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Datepicker</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> </head> <body> <app-root></app-root> </body> </html>
Step 4: Create a Custom Material Module File.
Inside the src,>> app folder, create one file called material.module.ts and add the following code.
// material.module.ts import { NgModule } from '@angular/core'; import { MatDatepickerModule } from '@angular/material'; @NgModule({ imports: [ MatDatepickerModule ], exports: [ MatDatepickerModule ] }) export class MaterialModule {}
We have imported MatDatepickerModule, MatNativeDateModule, and other components that we need in our Angular Datepicker Example App.
We can add additional components in the future if we need to.
This file is written on its own because it is easy to include all the Material components in this file, and then this file will be imported inside the app.module.ts.
// material.module.ts import { NgModule } from '@angular/core'; import { MatDatepickerModule, MatNativeDateModule, MatFormFieldModule, MatInputModule } from '@angular/material'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ imports: [ MatDatepickerModule, MatFormFieldModule, MatNativeDateModule, MatInputModule, BrowserAnimationsModule ], exports: [ MatDatepickerModule, MatFormFieldModule, MatNativeDateModule, MatInputModule, BrowserAnimationsModule ], providers: [ MatDatepickerModule ], }) export class MaterialModule {}
Step 5: Import MaterialModule in an app.module.ts file.
Import MaterialModule inside the app.module.ts file.
// app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { MaterialModule } from './material.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, MaterialModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Also, finally, write the Datepicker HTML code inside the app.component.html file.
<!-- app.component.html --> <mat-form-field> <input matInput [matDatepicker]="picker" placeholder="Choose a date"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field>
Save the file, go to a terminal or cmd, and start Angular Development Server.
ng serve --open
Go to the browser, and see something like the below image.
Step 6: Connecting a datepicker to an input
A datepicker comprises text input and a calendar popup, connected via the matDatePicker property on the text input.
<input [matDatepicker]="myDatepicker"> <mat-datepicker #myDatepicker></mat-datepicker>
There is an optional datepicker toggle button available. The toggle button can be added to the example above:
<input [matDatepicker]="myDatepicker"> <mat-datepicker-toggle [for]="myDatepicker"></mat-datepicker-toggle> <mat-datepicker #myDatepicker></mat-datepicker>
It works the same with an input that is part of a <mat-form-field> and a toggle button can easily be used as a prefix or suffix on the material input:
<mat-form-field> <input matInput [matDatepicker]="myDatepicker"> <mat-datepicker-toggle matSuffix [for]="myDatepicker"></mat-datepicker-toggle> <mat-datepicker #myDatepicker></mat-datepicker> </mat-form-field>
Step 7: Setting the calendar starting view
The startView property of <mat-datepicker> could be used to set the look that will show up when the calendar first opens. It can be configured to month, year, or multi-year; by default, it will begin to month view.
A month, year, or range of years that a calendar opens to is determined by first checking if any date is currently selected, and if so, it will open to a month or year containing that date. Otherwise, it will open in a month or year, providing today’s date.
This behavior can be easily overridden using the startAt property of <mat-datepicker>. In this case, a calendar will open to the month or year containing the startAt date.
<mat-form-field> <input matInput [matDatepicker]="picker" placeholder="Choose a date"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker> </mat-form-field>
You can find the code on Github.
Angular Datepicker Validation
Three properties add the date validation to the datepicker input.
The first two are the min and max properties.
Also, to enforce validation on input, these properties will disable all the dates on the calendar popup before or after the respective values and prevent the user from advancing the calendar past the month or year (depending on current view) containing the min or max date.
See the following HTML markup.
<mat-form-field class="example-full-width"> <input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="picker" placeholder="Choose a date"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field>
Also, see the typescript file related to the above markup.
import {Component} from '@angular/core'; /** @title Datepicker with min & max validation */ @Component({ selector: 'datepicker-min-max-example', templateUrl: 'datepicker-min-max-example.html', styleUrls: ['datepicker-min-max-example.css'], }) export class DatepickerMinMaxExample { minDate = new Date(2000, 0, 1); maxDate = new Date(2020, 0, 1); }
The second way to add the date validation is by using the matDatepickerFilter property of the datepicker input.
This property accepts a function of <D> => boolean (where <D> is the date type used by the datepicker, see Choosing a date implementation).
A true result indicates that the date is valid, and a false result suggests that it is not.
Again this will also disable the dates on a calendar that are invalid.
However, a critical difference between using matDatepickerFilter vs. using min or max is that filtering out all dates before or after a certain point will not prevent a user from advancing a calendar past that point.
See the following code example. See first the HTML markup.
<mat-form-field class="example-full-width"> <input matInput [matDatepickerFilter]="myFilter" [matDatepicker]="picker" placeholder="Choose a date"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field>
Now, see the Typescript file related to the above markup.
import {Component} from '@angular/core'; /** @title Datepicker with filter validation */ @Component({ selector: 'datepicker-filter-example', templateUrl: 'datepicker-filter-example.html', styleUrls: ['datepicker-filter-example.css'], }) export class DatepickerFilterExample { myFilter = (d: Date): boolean => { const day = d.getDay(); // Prevent Saturday and Sunday from being selected. return day !== 0 && day !== 6; } }
In this example, the user can go back past 2005, but all of the dates before then will be unselectable. They will not be able to go further back in the calendar than 2000.
If they manually type in a date before the min, after the max, or filtered out, the input will have validation errors.
Each validation property has a different error that can be checked:
- For example, the value that violates a min property will have the matDatepickerMin error.
- The value that violates a max property will have the matDatepickerMax error.
- The value that violates a matDatepickerFilter property will have the matDatepickerFilter error.
Angular Input and change events
The input’s native (input) and (change) events will only trigger user interaction with the input element; they will not fire when the user selects the date from the calendar popup.
Therefore, a datepicker input also has support for (dateInput) and (dateChange) events — these triggers when a user interacts with either an input or the popup.
The (dateInput) event will fire whenever the value changes due to the user typing or selecting a date from the calendar. Likewise, the (dateChange) event will fire whenever the user finishes typing input (on <input> blur) or when a user chooses the date from a calendar.
See the following HTML Markup.
<mat-form-field> <input matInput [matDatepicker]="picker" placeholder="Input & change events" (dateInput)="addEvent('input', $event)" (dateChange)="addEvent('change', $event)"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field> <div class="example-events"> <div *ngFor="let e of events">{{e}}</div> </div>
Now, see the typescript file related to that markup.
import {Component} from '@angular/core'; import {MatDatepickerInputEvent} from '@angular/material/datepicker'; /** @title Datepicker input and change events */ @Component({ selector: 'datepicker-events-example', templateUrl: 'datepicker-events-example.html', styleUrls: ['datepicker-events-example.css'], }) export class DatepickerEventsExample { events: string[] = []; addEvent(type: string, event: MatDatepickerInputEvent) { this.events.push(`${type}: ${event.value}`); } }
Disabling parts of the Angular Datepicker
As with any standard <input>, it is possible to disable the datepicker input by adding the disabled property.
By default, the <mat-datepicker> and <mat-datepicker-toggle> will inherit their disabled state from the <input>, but this can be overridden by setting a disabled property on the datepicker or toggle elements.
This is very useful if you want to disable the text input but allow selection via the calendar or vice-versa.
See the following HTML Markup.
<p> <mat-form-field> <input matInput [matDatepicker]="dp1" placeholder="Completely disabled" disabled> <mat-datepicker-toggle matSuffix [for]="dp1"></mat-datepicker-toggle> <mat-datepicker #dp1></mat-datepicker> </mat-form-field> </p> <p> <mat-form-field> <input matInput [matDatepicker]="dp2" placeholder="Popup disabled"> <mat-datepicker-toggle matSuffix [for]="dp2" disabled></mat-datepicker-toggle> <mat-datepicker #dp2></mat-datepicker> </mat-form-field> </p> <p> <mat-form-field> <input matInput [matDatepicker]="dp3" placeholder="Input disabled" disabled> <mat-datepicker-toggle matSuffix [for]="dp3"></mat-datepicker-toggle> <mat-datepicker #dp3 disabled="false"></mat-datepicker> </mat-form-field> </p>
Now, see the typescript file.
import {Component} from '@angular/core'; /** @title Disabled datepicker */ @Component({ selector: 'datepicker-disabled-example', templateUrl: 'datepicker-disabled-example.html', styleUrls: ['datepicker-disabled-example.css'], }) export class DatepickerDisabledExample {}
That’s it for this tutorial.
Hi ,
can you tell me hot to set the date format to yyyy/mm/dd
I’m using mat-datepicker and I need to select only month and year from the date picker, is there any solution??
What is it with Angular?
“How do I add a date picker?”, something that in Dot Net involves a single line of code with the behaviour and variables related to that object created automatically, but every tutorial I have seen on every control in Angular so far starts with instructions on how to create a project from scratch but here in order to implement it I need to create a material module to determine what it looks like?
Why does adding a single control seem to involve 10-20 lines of code no matter what one does?
Bare bones….minimum coding…just a date time picker…nothing else.