starlight
starlight

Reputation: 785

How to pick date range in angular material 5.0.0 with datepicker?

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

Answers (10)

Rahul Dudhane
Rahul Dudhane

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

Manu
Manu

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

Edmilson Lani
Edmilson Lani

Reputation: 153

Now available in Angular Material v10.0.1 or more

https://material.angular.io/components/datepicker/overview#date-range-selection

Upvotes: 3

Jeannot
Jeannot

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

Abdun Nahid
Abdun Nahid

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.

Preview

You can check this out in NPM

Upvotes: 5

FirstVertex
FirstVertex

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:

Screenshot of the Material date range picker

Upvotes: 19

mariogarcia
mariogarcia

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

anurag619
anurag619

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

Oswald
Oswald

Reputation: 1262

There's an open issue at the github page.

https://github.com/angular/material2/issues/4763

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

Edric
Edric

Reputation: 26730

There's currently no possible way to select a range of dates, although there's an issue requesting so.

Upvotes: 8

Related Questions