Reputation: 785
I am using the latest Angular Material 5.0.0-rc0
in my Angular 5 app. I am trying to select a range of dates with the datepicker
provided with Angular material, but I couldn't find any documentation regarding that.
All I could work with it is to select a startDate
or set the minDate
and maxDate
. Here's the HTML code for that
<mat-form-field>
<input matInput [min]="minDate" [max]="maxDate" [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>
and TS code
import {Component} from '@angular/core';
@Component({
selector: 'datepicker-start-view-example',
templateUrl: 'datepicker-start-view-example.html',
styleUrls: ['datepicker-start-view-example.css'],
})
export class DatepickerStartViewExample {
minDate = new Date(2000, 0, 1);
maxDate = new Date(2020, 0, 1);
}
This code helps me select one date in the range of those min and max dates but doesn't allow to select a range of them. Though using a third-party library may solve this problem, but its gonna have a different UI, which is going to be different from my current app's UI. Please help me solve this issue.
Upvotes: 28
Views: 60344
Reputation: 554
Yes, it is possible by using mat-calendar
. You need to use DateRange
and pass it to the selected
attribute of mat-calendar
.
After doing this you need to handle some cases on selectedChange
method of mat-calendar
. Working example is given below:
In html file
<mat-calendar [selected]="selectedDate"
(selectedChange)="onSlotChange($event)">
</mat-calendar>
In ts file declare and add following method
selectedDate: DateRange<Date>;
onSlotChange(changedDate: Date) {
if (!this.selectedDate) {
this.selectedDate = new DateRange(changedDate, changedDate);
} else if (this.selectedDate.start > changedDate && !this.selectedDate.end) {
this.selectedDate = new DateRange(changedDate, this.selectedDate.start);
} else if (this.selectedDate.start > changedDate && this.selectedDate.end) {
this.selectedDate = new DateRange(changedDate, this.selectedDate.end);
} else {
this.selectedDate = new DateRange(this.selectedDate.start, changedDate);
}
}
This will do your work. All the best!
Upvotes: 0
Reputation: 33
May be this can help you:
<mat-form-field>
<mat-label>Custom date</mat-label>
<input matInput type="datetime-local">
</mat-form-field>
Upvotes: 0
Reputation: 153
Now available in Angular Material v10.0.1 or more
https://material.angular.io/components/datepicker/overview#date-range-selection
Upvotes: 3
Reputation: 51
It is totally possible to do it but not directly with mat-datepicker component. Actually, mat-datepicker uses mat-menu component to display a mat-calendar component.
To perform what you ask, you could use something like below.
In your component.html file
<mat-menu #startDateRangeMenu="matMenu">
<mat-calendar
#calendar
(click)="$event.stopPropagation()"
(selectedChange)="toggleStartDateDate($event, calendar)"
[dateClass]="isStartDateDateSelected()">
</mat-calendar>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="startDateRangeMenu">
{{'startDate' | translate}}
</button>
In your .ts file
isStartDateSelected() {
return (date: Date): MatCalendarCellCssClasses => {
const dateMoment = moment(date);
let startDate;
let endDate;
if (this.startDateAfter) {
startDate = moment(this.startDateAfter);
}
if (this.startDateBefore) {
endDate = moment(this.startDateBefore);
}
if (startDate && endDate && dateMoment.isBetween(startDate, endDate, 'days', '[]')) {
return 'date-selected';
} else if (startDate && dateMoment.isSame(startDate)) {
return 'date-selected';
} else if (moment().startOf('day').isSame(moment(date).startOf('day'))) {
return 'today';
}
return;
};
}
toggleStartDateDate(date: any, calendar: any) {
const dateString = moment(date).format('YYYY-MM-DD');
if (this.selectStartDateType === 'startDateAfter') {
this.startDateAfter = dateString;
this.startDateBefore = dateString;
this.selectStartDateType = 'startDateBefore';
} else {
if (moment(date).isBefore(moment(this.startDateAfter))) {
this.startDateAfter = dateString;
this.startDateBefore = dateString;
this.selectStartDateType = 'startDateBefore';
} else {
this.startDateBefore = dateString;
this.selectStartDateType = 'startDateAfter';
}
}
calendar.updateTodaysDate();
}
In your .css file
::ng-deep .date-selected .mat-calendar-body-cell-content {
background-color: #17a2b8;
color: white;
}
::ng-deep .date-selected.mat-calendar-body-cell:hover .mat-calendar-body-cell-content {
background-color: #17a2b8 !important;
}
Upvotes: 0
Reputation: 311
It is even not possible in Angular Material 7.0.0. There are different plugins to do so. I came up with ngx-aaa-datepicker. It worked for me.
You can check this out in NPM
Upvotes: 5
Reputation: 3785
Recommend to check out Saturn Material range Datepicker. Have a look also at their demo page. It is a full Material UX with built-in support for your existing Material theme.
You can install it with npm install saturn-datepicker
. See their Github page for full integration instructions.
Markup looks like this:
<mat-form-field>
<input matInput
placeholder="Choose a date"
[satDatepicker]="picker"
[value]="date">
<sat-datepicker #picker [rangeMode]="true"></sat-datepicker>
<sat-datepicker-toggle matSuffix [for]="picker"></sat-datepicker-toggle>
</mat-form-field>
And here is what it ends up looking like on the page:
Upvotes: 19
Reputation: 171
In the mean time you could just have two date pickers. One for the start date and one for the end date. Something like this:
<mat-form-field> //start date datepicker
<input matInput [min]="minDate" [max]="maxDate" [formControl]="startDate" [matDatepicker]="picker" placeholder="Choose a start date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker startView="year" [startAt]="minDate"></mat-datepicker>
</mat-form-field>
<mat-form-field> //end date datepicker
<input matInput [min]="startDate" [max]="maxDate" [formControl]="endDate" [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 could then have some where if they change the endDate
to something before the startDate
it shows them an error or resets the startDate
Upvotes: 6
Reputation: 712
The Angular version of the Angular UI Bootstrap library has a date range selector, you can check out that. I am using it in my projects.
https://ng-bootstrap.github.io/#/components/datepicker/examples
Upvotes: 3
Reputation: 1262
There's an open issue at the github page.
In Angular-Blog, there's a note for this too (look at the end).
https://blog.angular.io/taking-advantage-of-the-angular-material-datepicker-237e80fa14b3
Upvotes: 4