mat-daterangepicker
Version:
Angular material date picker extension to support range selection.
993 lines (985 loc) • 56.7 kB
JavaScript
import { __extends, __decorate, __param, __awaiter, __generator } from 'tslib';
import { EventEmitter, ReflectiveInjector, Optional, Inject, ChangeDetectorRef, Injector, Input, Output, Component, ViewEncapsulation, ChangeDetectionStrategy, ViewChild, ViewChildren, InjectionToken, NgZone, ViewContainerRef, forwardRef, ElementRef, Directive, ComponentFactoryResolver, NgModule } from '@angular/core';
import { DOCUMENT, CommonModule } from '@angular/common';
import { A11yModule } from '@angular/cdk/a11y';
import { Overlay, OverlayModule } from '@angular/cdk/overlay';
import { ComponentPortal, PortalModule } from '@angular/cdk/portal';
import { DateAdapter, MAT_DATE_FORMATS, MatNativeDateModule } from '@angular/material/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { MatCalendar, MatDatepickerIntl, matDatepickerAnimations, MatDatepickerContent, MAT_DATEPICKER_SCROLL_STRATEGY, MatDatepicker, MatDatepickerInputEvent, MatDatepickerInput, MatMonthView, MatCalendarBody, MatDatepickerToggle, MatDatepickerModule } from '@angular/material/datepicker';
import { BehaviorSubject, Subject, Subscription } from 'rxjs';
import { Directionality } from '@angular/cdk/bidi';
import { take } from 'rxjs/operators';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import { MatFormField } from '@angular/material/form-field';
import { MAT_INPUT_VALUE_ACCESSOR } from '@angular/material/input';
/*
RANGE: Most of the code is redundant and hera as inheritance boilerplate.
The relevant code is marked with a comment.
*/
var MatDaterangeCalendar = /** @class */ (function (_super) {
__extends(MatDaterangeCalendar, _super);
// THIS SECTION IS JUST TO PROVIDE MatCalendar as SgCalendar to MatCalendarHeader
function MatDaterangeCalendar(_intl, _dateAdapter, _dateFormats, changeDetectorRef, drInjector) {
var _this = _super.call(this, _intl, _dateAdapter, _dateFormats, changeDetectorRef) || this;
_this.drInjector = drInjector;
_this.selectedRangeEndChange = new EventEmitter();
return _this;
}
MatDaterangeCalendar.prototype.ngAfterContentInit = function () {
_super.prototype.ngAfterContentInit.call(this);
var injector = ReflectiveInjector.resolveAndCreate([{ provide: MatCalendar, useValue: this }], this.drInjector);
this._calendarHeaderPortal.injector = injector;
var activeDate = this.startAt || this['_dateAdapter'].today();
this.activeDate = this.view === 0 ? activeDate : this.getSecondViewActiveDate(activeDate);
// Assign to the private property since we don't want to move focus on init.
// this._currentView = this.startView;
};
Object.defineProperty(MatDaterangeCalendar.prototype, "selectedRangeEnd", {
get: function () { return this._selectedRangeEnd; },
set: function (value) {
this._selectedRangeEnd = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
},
enumerable: true,
configurable: true
});
MatDaterangeCalendar.prototype._dateSelectedRangeEnd = function (date) {
if (!this._dateAdapter.sameDate(date, this.selectedRangeEnd)) {
this.selectedRangeEndChange.emit(date);
}
};
MatDaterangeCalendar.prototype.getSecondViewActiveDate = function (activeDate) {
var date = this['_dateAdapter'].getDate(activeDate);
var month = this['_dateAdapter'].getMonth(activeDate);
var year = this['_dateAdapter'].getYear(activeDate);
var y, m;
if (month === 11) {
m = 0;
y = year + 1;
}
else {
m = month + 1,
y = year;
}
var D = this['_dateAdapter'].createDate(y, m, date);
return D;
};
MatDaterangeCalendar.ctorParameters = function () { return [
{ type: MatDatepickerIntl },
{ type: DateAdapter, decorators: [{ type: Optional }] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAT_DATE_FORMATS,] }] },
{ type: ChangeDetectorRef },
{ type: Injector }
]; };
__decorate([
Input()
], MatDaterangeCalendar.prototype, "view", void 0);
__decorate([
Input()
], MatDaterangeCalendar.prototype, "setHoverCells", void 0);
__decorate([
Input()
], MatDaterangeCalendar.prototype, "clearBody", void 0);
__decorate([
Input()
], MatDaterangeCalendar.prototype, "range", void 0);
__decorate([
Input()
], MatDaterangeCalendar.prototype, "selectedRangeEnd", null);
__decorate([
Output()
], MatDaterangeCalendar.prototype, "selectedRangeEndChange", void 0);
MatDaterangeCalendar = __decorate([
Component({
selector: 'mat-daterange-calendar',
template: "<!-- \n\tRANGE: Most of the code is redundant and hera as inheritance boilerplate.\n\tThe relevant code is marked with a comment.\n\tADDED LOC ~3\n-->\n<ng-template [cdkPortalOutlet]=\"_calendarHeaderPortal\"></ng-template>\n\n<div class=\"mat-calendar-content\" [ngSwitch]=\"currentView\" cdkMonitorSubtreeFocus tabindex=\"-1\">\n\n\t<mat-daterange-month-view\n\t\t*ngSwitchCase=\"'month'\"\n\t\t[view]=\"view\"\n\t\t[activeDate]=\"activeDate\"\n\t\t[selected]=\"selected\"\n\t\t[dateFilter]=\"dateFilter\"\n\t\t[maxDate]=\"maxDate\"\n\t\t[minDate]=\"minDate\"\n\t\t(selectedChange)=\"_dateSelected($event)\"\n\t\t(_userSelection)=\"_userSelected()\"\n\n\t\t[range]=\"range\"\n\t\t[setHoverCells]=\"setHoverCells\"\n\t\t[clearBody]=\"clearBody\"\n\t\t[selectedRangeEnd]=\"selectedRangeEnd\"\n\t\t(selectedRangeEndChange)=\"_dateSelectedRangeEnd($event)\">\n\t\t<!-- THE 3 LINES ABOVE ARE THE ONLY ADDITION -->\n\t</mat-daterange-month-view>\n\n\t<mat-year-view\n\t\t*ngSwitchCase=\"'year'\"\n\t\t[activeDate]=\"activeDate\"\n\t\t[selected]=\"selected\"\n\t\t[dateFilter]=\"dateFilter\"\n\t\t[maxDate]=\"maxDate\"\n\t\t[minDate]=\"minDate\"\n\t\t(monthSelected)=\"_monthSelectedInYearView($event)\"\n\t\t(selectedChange)=\"_goToDateInView($event, 'month')\">\n\t</mat-year-view>\n\n\t<mat-multi-year-view\n\t\t*ngSwitchCase=\"'multi-year'\"\n\t\t[activeDate]=\"activeDate\"\n\t\t[selected]=\"selected\"\n\t\t[dateFilter]=\"dateFilter\"\n\t\t[maxDate]=\"maxDate\"\n\t\t[minDate]=\"minDate\"\n\t\t(yearSelected)=\"_yearSelectedInMultiYearView($event)\"\n\t\t(selectedChange)=\"_goToDateInView($event, 'year')\">\n\t</mat-multi-year-view>\n</div>\n\n",
host: {
'class': 'mat-calendar',
},
exportAs: 'matDaterangeCalendar',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
}),
__param(1, Optional()),
__param(2, Optional()), __param(2, Inject(MAT_DATE_FORMATS))
], MatDaterangeCalendar);
return MatDaterangeCalendar;
}(MatCalendar));
/*
RANGE: Most of the code is redundant and hera as inheritance boilerplate.
The relevant code is marked with a comment.
*/
var MatDaterangepickerContent = /** @class */ (function (_super) {
__extends(MatDaterangepickerContent, _super);
function MatDaterangepickerContent() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._onApplyRange = new EventEmitter();
_this.setHoverCells = new BehaviorSubject(null);
_this.clearBody = new BehaviorSubject(null);
return _this;
}
Object.defineProperty(MatDaterangepickerContent.prototype, "drDatepicker", {
get: function () {
return this.datepicker;
},
enumerable: true,
configurable: true
});
MatDaterangepickerContent.prototype.ngOnInit = function () {
};
MatDaterangepickerContent.prototype.ngAfterViewInit = function () {
};
// THIS IS THE ONLY ADDITION
MatDaterangepickerContent.prototype.onUserSelection = function (view) {
this.drDatepicker._userSelection();
};
MatDaterangepickerContent.prototype.applyRange = function () {
if (this.drDatepicker.applyButton) {
this.drDatepicker.applyRange();
}
};
MatDaterangepickerContent.prototype.clearRange = function () {
this.drDatepicker.clearRange();
this.clearBody.next(true);
this.datepicker._selected = null;
this.drDatepicker._selectedRangeEnd = null;
};
MatDaterangepickerContent.prototype.setCustomRange = function (range) {
if (!range.startDate || !range.endDate)
return;
this.datepicker._selected = range.startDate;
this.drDatepicker._selectedRangeEnd = range.endDate;
this.datepicker._selectedChanged.next(range.startDate);
this.drDatepicker._selectedChangedRangeEnd.next(range.endDate);
this.setActiveDate(range.startDate, range.endDate);
};
MatDaterangepickerContent.prototype.isSameRange = function (range) {
if (!this.datepicker._selected || !this.drDatepicker._selectedRangeEnd || !range.startDate || !range.endDate)
return;
return this.drDatepicker._drDateAdapter.compareDate(range.startDate, this.datepicker._selected) == 0 &&
this.drDatepicker._drDateAdapter.compareDate(range.endDate, this.drDatepicker._selectedRangeEnd) == 0;
};
MatDaterangepickerContent.prototype.isSomeRange = function () {
var _this = this;
if (!this.datepicker._selected || !this.drDatepicker._selectedRangeEnd)
return false;
return this.drDatepicker.customRanges.some(function (range) { return _this.isSameRange(range); });
};
MatDaterangepickerContent.prototype.getWidthDateRangePicker = function () {
if (this.drDatepicker.dualView) {
if (this.drDatepicker.showCustomRanges && this.drDatepicker.customRanges.length) {
return '655px';
}
return '600px';
}
if (this.drDatepicker.showCustomRanges && this.drDatepicker.customRanges.length) {
return '450px';
}
};
MatDaterangepickerContent.prototype.setActiveDate = function (from, to) {
var fromMonth = this.drDatepicker._drDateAdapter.getMonth(from);
var toMonth = this.drDatepicker._drDateAdapter.getMonth(to);
var toYear = this.drDatepicker._drDateAdapter.getYear(to);
var toDate = this.drDatepicker._drDateAdapter.getDate(to);
var y, m;
if (toMonth === 11) {
m = 0;
y = toYear + 1;
}
else {
m = toMonth + 1,
y = toYear;
}
var endDate = this.drDatepicker._drDateAdapter.createDate(y, m, 1);
this.calendars.forEach(function (calendar, i) {
if (i === 0) {
calendar.activeDate = from;
}
else {
if (fromMonth !== toMonth) { // if start month & end month are differents
calendar.activeDate = to;
}
else {
calendar.activeDate = endDate;
}
}
});
};
__decorate([
ViewChild(MatDaterangeCalendar, { static: true })
], MatDaterangepickerContent.prototype, "_calendar", void 0);
__decorate([
ViewChildren(MatDaterangeCalendar)
], MatDaterangepickerContent.prototype, "calendars", void 0);
MatDaterangepickerContent = __decorate([
Component({
selector: 'mat-daterangepicker-content',
template: "<div>\n\t<!-- \n\t\tRANGE: Most of the code is redundant and hera as inheritance boilerplate.\n\t\tThe relevant code is marked with a comment.\n\t\tADDED LOC ~3\n\t-->\n\t<div class=\"mat-daterange-calendars\" [ngStyle]=\"{'width': getWidthDateRangePicker()}\">\n\t\t<div *ngIf=\"drDatepicker.showCustomRanges && drDatepicker.customRanges.length\" class=\"mat-daterange-custom-ranges\">\n\t\t\t<button *ngFor=\"let range of drDatepicker.customRanges\" mat-flat-button [color]=\"isSameRange(range) ? 'primary' : ''\" (click)=\"setCustomRange(range)\" class=\"mat-daterange-calendar-button-action\">{{range.name}}</button>\n\t\t\t<button mat-flat-button [color]=\"!isSomeRange() ? 'primary' : ''\" class=\"mat-daterange-custom-range mat-daterange-calendar-button-action\">Custom Range</button>\n\t\t</div>\n\t\t<mat-daterange-calendar *ngFor=\"let view of drDatepicker._getViews()\" #Calendar cdkTrapFocus\n\t\t\t\t\t[id]=\"datepicker.id\"\n\t\t\t\t\t[ngClass]=\"datepicker.panelClass\"\n\t\t\t\t\tclass=\"mat-daterange-calendar\"\n\t\t\t\t\t[view]=\"view\"\n\t\t\t\t\t[setHoverCells]=\"setHoverCells\"\n\t\t\t\t\t[clearBody]=\"clearBody\"\n\t\t\t\t\t\n\t\t\t\t\t[startAt]=\"datepicker.startAt\"\n\t\t\t\t\t[startView]=\"datepicker.startView\"\n\t\t\t\t\t[minDate]=\"datepicker._minDate\"\n\t\t\t\t\t[maxDate]=\"datepicker._maxDate\"\n\t\t\t\t\t[dateFilter]=\"datepicker._dateFilter\"\n\t\t\t\t\t[headerComponent]=\"datepicker.calendarHeaderComponent\"\n\t\t\t\t\t[selected]=\"datepicker._selected\"\n\t\t\t\t\t[@fadeInCalendar]=\"'enter'\"\n\t\t\t\t\t(selectedChange)=\"datepicker.select($event)\"\n\t\t\t\t\t(yearSelected)=\"datepicker._selectYear($event)\"\n\t\t\t\t\t(monthSelected)=\"datepicker._selectMonth($event)\"\n\n\t\t\t\t\t[range]=\"!!drDatepicker._datepickerInputRangeEnd\"\n\t\t\t\t\t[selectedRangeEnd]=\"drDatepicker._selectedRangeEnd\"\n\t\t\t\t\t(selectedRangeEndChange)=\"drDatepicker.selectRangeEnd($event)\"\n\t\t\t\t\t(_userSelection)=\"onUserSelection(view)\">\n\t\t\t\t\t<!-- \n\t\t\t\t\t\t\tTHE 3 LINES ABOVE ARE THE ONLY ADDITION\n\t\t\t\t\t\t\tThe _userSelection will pass logic handling to the datepicker component\n\t\t\t\t\t\t\tinstead of closing the dialog/popup, this is because range logic is handled there.\n\n\t\t\t\t\t\t\tThe other attributes are passing on the additional date (Range end) bindings\n\t\t\t\t\t\t\tand a flag that sets range on/off based on the input range.\n\t\t\t\t\t\t\tThis means that an *ngIf on that input by the user can toggle range on/off without\n\t\t\t\t\t\t\ta special flag.\n\t\t\t\t\t-->\n\n\t\t</mat-daterange-calendar>\n\t</div>\n\n\t<div *ngIf=\"drDatepicker.applyButton\" class=\"mat-daterange-calendar-actions\">\n\t\t<button mat-button color=\"primary\" (click)=\"clearRange()\">Clear</button> \n\t\t<button mat-flat-button color=\"primary\" (click)=\"applyRange()\">Apply</button>\n\t</div>\n</div>",
host: {
'class': 'mat-datepicker-content',
'[@transformPanel]': '"enter"',
'[class.mat-datepicker-content-touch]': 'datepicker.touchUi',
'[class.mat-datepicker-content-above]': '_isAbove',
},
animations: [
matDatepickerAnimations.transformPanel,
matDatepickerAnimations.fadeInCalendar,
],
exportAs: 'matDaterangepickerContent',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
inputs: ['color'],
styles: [".mat-daterange-calendar-body-in-range{background-color:rgba(63,81,181,.15)}.mat-daterange-calendar-body-in-range.mat-daterange-calendar-body-range-start{border-radius:100% 0 0 100%}.mat-daterange-calendar-body-in-range.mat-daterange-calendar-body-range-end{border-radius:0 100% 100% 0}.mat-daterange-calendars{display:flex}.mat-daterange-calendar{flex-grow:1}.mat-daterange-calendar-actions{padding:15px;text-align:right}.mat-daterange-custom-ranges{display:flex;flex-flow:column;width:130px;padding:8px}.mat-daterange-custom-ranges button{text-align:left;font-size:12px;line-height:32px;font-weight:400!important}.mat-daterange-calendar-button-action{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}"]
})
], MatDaterangepickerContent);
return MatDaterangepickerContent;
}(MatDatepickerContent));
var thisMonthRange = function () {
var y = new Date().getFullYear();
var m = new Date().getMonth();
var yearFrom, monthFrom, yearTo, monthTo;
yearFrom = y;
monthFrom = m;
yearTo = y;
monthTo = m + 1;
if (m === 11) {
yearTo = y + 1;
monthTo = 0;
}
return {
name: 'This Month',
startDate: new Date(yearFrom, monthFrom, 1),
endDate: new Date(yearTo, monthTo, 0)
};
};
var ɵ0 = thisMonthRange;
var lastMonthRange = function () {
var y = new Date().getFullYear();
var m = new Date().getMonth();
var yearFrom, monthFrom, yearTo, monthTo;
yearFrom = y;
monthFrom = m - 1;
yearTo = y;
monthTo = m;
if (m === 0) {
yearFrom = y - 1;
monthFrom = 11;
}
return {
name: 'Last Month',
startDate: new Date(yearFrom, monthFrom, 1),
endDate: new Date(yearTo, monthTo, 0)
};
};
var ɵ1 = lastMonthRange;
var lastThreeMonthsRange = function () {
var y = new Date().getFullYear();
var m = new Date().getMonth();
var yearFrom, monthFrom, yearTo, monthTo;
yearFrom = y;
monthFrom = m - 3; // current month - number desired
yearTo = y;
monthTo = m;
if (monthFrom < 0) {
yearFrom = y - 1;
monthFrom = 11 + 1 + monthFrom;
}
return {
name: 'Last 3 Months',
startDate: new Date(yearFrom, monthFrom, 1),
endDate: new Date(yearTo, monthTo, 0)
};
};
var ɵ2 = lastThreeMonthsRange;
var DEFAULT_DATES_RANGES = [
{ name: 'Today', startDate: new Date(), endDate: new Date() },
{ name: 'Yesterday', startDate: new Date(new Date().setDate(new Date().getDate() - 1)), endDate: new Date(new Date().setDate(new Date().getDate() - 1)) },
{ name: 'Last 7 Days', startDate: new Date(new Date().setDate(new Date().getDate() - 6)), endDate: new Date() },
{ name: 'Last 30 Days', startDate: new Date(new Date().setDate(new Date().getDate() - 29)), endDate: new Date() },
thisMonthRange(),
lastMonthRange(),
lastThreeMonthsRange(),
];
/*
RANGE: Most of the code is redundant and hera as inheritance boilerplate.
The added/edited code adds logic for handling 1 or 2 inputs, i.e. range.
When we have 2 inputs it's a range, otherwise its a single value date selection.
The main logic is in `selectRangeEnd()` which handles range/non-range and inner range states. (this could
probably be more orgenaized with proper states for clarity)
Instead of "_userSelection" closing the popup/dialog from the calendar-content, the logic
is moved here into _userSelection() which will close/keep based on range logic.
*/
var MAT_DEFAULT_DATES_RANGES = new InjectionToken('Custom Ranges');
var ɵ0$1 = [];
var MatDaterangepicker = /** @class */ (function (_super) {
__extends(MatDaterangepicker, _super);
function MatDaterangepicker(_drDialog, _drOverlay, _drNgZone, _drViewContainerRef, _drScrollStrategy, _drDateAdapter, _drDir, _drDocument, _customRanges) {
var _this = _super.call(this, _drDialog = Object.create(_drDialog), _drOverlay, _drNgZone, _drViewContainerRef, _drScrollStrategy, _drDateAdapter, _drDir, _drDocument) || this;
_this._drOverlay = _drOverlay;
_this._drNgZone = _drNgZone;
_this._drViewContainerRef = _drViewContainerRef;
_this._drScrollStrategy = _drScrollStrategy;
_this._drDateAdapter = _drDateAdapter;
_this._drDir = _drDir;
_this._drDocument = _drDocument;
_this._customRanges = _customRanges;
_this.applyButton = true;
_this.dualView = true;
_this.showCustomRanges = false;
_this.apply = new EventEmitter();
_this.customRanges = [];
_this._validSelectedRangeEnd = null;
/** Emits new selected date when selected date changes. */
_this._selectedChangedRangeEnd = new Subject();
_this._clearRangeEnd = new Subject();
_this._range = false;
_this._inputRangeEndSubscription = Subscription.EMPTY;
/*
This is a monkey patch workaround to support a new component for dialog/popup.
Because everything is freaking private in material, why would somone use protected anyway.
*/
_this._drDialog = _drDialog;
_this._drDialog.open = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (typeof args[0].createEmbeddedView !== 'function') {
args[0] = MatDaterangepickerContent;
}
return MatDialog.prototype.open.apply(_drDialog, args);
};
// Object.defineProperty(this, '_calendarPortal', {
// get: function () { return this.__calendarPortal; },
// set: function (value) {
// this.__calendarPortal = value;
// if (value) {
// value.component = MatDaterangepickerContent;
// }
// }
// })
_this['_openAsPopup'] = function () {
var portal = new ComponentPortal(MatDaterangepickerContent, _this._drViewContainerRef);
_this['_destroyPopup']();
_this['_createPopup']();
_this['_popupComponentRef'] = _this['_popupRef'].attach(portal);
_this.forwardContentValues(_this['_popupComponentRef'].instance);
// Update the position once the calendar has rendered.
_this._drNgZone.onStable.asObservable().pipe(take(1)).subscribe(function () {
_this['_popupRef'].updatePosition();
});
};
return _this;
}
Object.defineProperty(MatDaterangepicker.prototype, "_selectedRangeEnd", {
/** The currently selected date. */
get: function () { return this._validSelectedRangeEnd; },
set: function (value) { this._validSelectedRangeEnd = value; },
enumerable: true,
configurable: true
});
MatDaterangepicker.prototype.ngOnInit = function () {
if (this.customRanges) {
this._setCustomRanges();
}
};
MatDaterangepicker.prototype.ngAfterViewInit = function () {
};
MatDaterangepicker.prototype.forwardContentValues = function (instance) {
instance.datepicker = this;
instance.color = this.color;
};
MatDaterangepicker.prototype.ngOnDestroy = function () {
_super.prototype.ngOnDestroy.call(this);
this._inputRangeEndSubscription.unsubscribe();
};
MatDaterangepicker.prototype.selectRangeEnd = function (date) {
if (!this._range) {
_super.prototype.select.call(this, date);
}
else {
if (!date) {
if (this._selected && this._selectedRangeEnd) {
_super.prototype.select.call(this, null);
this._selectRangeEnd(null);
}
else if (this._selected) {
_super.prototype.select.call(this, null);
}
else if (this._selectedRangeEnd) {
this._selectRangeEnd(null);
}
}
else if (!this._selected || this._selectedRangeEnd) {
if (this._selectedRangeEnd) {
this._selectRangeEnd(null);
}
_super.prototype.select.call(this, date);
}
else {
if (date < this._selected) {
var swap = this._selected;
_super.prototype.select.call(this, date);
this._selectRangeEnd(swap);
}
else if (date >= this._selected) { // notice date === this._selected is not skipped
this._selectRangeEnd(date);
}
}
}
};
MatDaterangepicker.prototype._userSelection = function () {
if (this.applyButton)
return;
if (!this._range || (this._selected && this._selectedRangeEnd)) {
this.close();
}
};
MatDaterangepicker.prototype.applyRange = function () {
this.close();
this.apply.emit();
};
MatDaterangepicker.prototype.clearRange = function () {
this._datepickerInput.value = null;
this._clearRangeEnd.next();
};
MatDaterangepicker.prototype._getViews = function () {
if (this.dualView) {
return [0, 1];
}
return [0];
};
MatDaterangepicker.prototype._registerInputRangeEnd = function (input) {
var _this = this;
if (this._datepickerInputRangeEnd) {
throw Error('A MatDatepicker can only be associated with a single range end input.');
}
this._datepickerInputRangeEnd = input;
this._range = !!input;
this._inputRangeEndSubscription.unsubscribe();
if (this._range) {
this._inputRangeEndSubscription =
this._datepickerInputRangeEnd._valueChange.subscribe(function (value) { return _this._selectedRangeEnd = value; });
}
};
MatDaterangepicker.prototype._unregisterInputRangeEnd = function (input) {
if (this._datepickerInputRangeEnd) {
if (!input || input === this._datepickerInputRangeEnd) {
this._datepickerInputRangeEnd = undefined;
this._range = false;
this._inputRangeEndSubscription.unsubscribe();
}
}
};
MatDaterangepicker.prototype._selectRangeEnd = function (date) {
var oldValue = this._selectedRangeEnd;
this._selectedRangeEnd = date;
if (!this._drDateAdapter.sameDate(oldValue, this._selectedRangeEnd)) {
this._selectedChangedRangeEnd.next(this._selectedRangeEnd);
}
};
MatDaterangepicker.prototype._setCustomRanges = function () {
var _this = this;
if (this._customRanges.length) {
this.customRanges = this._customRanges;
}
else {
this.customRanges = DEFAULT_DATES_RANGES.map(function (range) {
return {
name: range.name,
startDate: range.startDate ? _this._drDateAdapter.createDate(range.startDate.getFullYear(), range.startDate.getMonth(), range.startDate.getDate()) : null,
endDate: range.endDate ? _this._drDateAdapter.createDate(range.endDate.getFullYear(), range.endDate.getMonth(), range.endDate.getDate()) : null
};
});
}
};
MatDaterangepicker.ctorParameters = function () { return [
{ type: MatDialog },
{ type: Overlay },
{ type: NgZone },
{ type: ViewContainerRef },
{ type: undefined, decorators: [{ type: Inject, args: [MAT_DATEPICKER_SCROLL_STRATEGY,] }] },
{ type: DateAdapter, decorators: [{ type: Optional }] },
{ type: Directionality, decorators: [{ type: Optional }] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] },
{ type: Array, decorators: [{ type: Inject, args: [MAT_DEFAULT_DATES_RANGES,] }] }
]; };
__decorate([
Input()
], MatDaterangepicker.prototype, "applyButton", void 0);
__decorate([
Input()
], MatDaterangepicker.prototype, "dualView", void 0);
__decorate([
Input()
], MatDaterangepicker.prototype, "showCustomRanges", void 0);
__decorate([
Output()
], MatDaterangepicker.prototype, "apply", void 0);
MatDaterangepicker = __decorate([
Component({
selector: 'mat-daterangepicker',
template: '',
exportAs: 'matDaterangepicker',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
providers: [
{ provide: MAT_DEFAULT_DATES_RANGES, useValue: ɵ0$1 },
]
}),
__param(4, Inject(MAT_DATEPICKER_SCROLL_STRATEGY)),
__param(5, Optional()),
__param(6, Optional()),
__param(7, Optional()), __param(7, Inject(DOCUMENT)),
__param(8, Inject(MAT_DEFAULT_DATES_RANGES))
], MatDaterangepicker);
return MatDaterangepicker;
}(MatDatepicker));
/*
RANGE: Most of the code is redundant and hera as inheritance boilerplate.
The relevant code adds simple logic for a 2nd input, combined with minimal changes in the
datepicker component, the work is done there so in native implementation this should have
minimal changes, perhaps using dedicated input without min/max/filter etc... which are only
set on the 1st input
*/
var SG_DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return MatDaterangepickerInputEnd; }),
multi: true
};
var SG_DATEPICKER_VALIDATORS = {
provide: NG_VALIDATORS,
useExisting: forwardRef(function () { return MatDaterangepickerInputEnd; }),
multi: true
};
var MatDaterangepickerInputEnd = /** @class */ (function (_super) {
__extends(MatDaterangepickerInputEnd, _super);
function MatDaterangepickerInputEnd(_drElementRef, _drDateAdapter, _drDateFormats, _drFormField) {
var _this = _super.call(this, _drElementRef, _drDateAdapter, _drDateFormats, _drFormField) || this;
_this._drElementRef = _drElementRef;
_this._drDateAdapter = _drDateAdapter;
_this._drDateFormats = _drDateFormats;
_this._drFormField = _drFormField;
_this._matDatepickerSubscription = Subscription.EMPTY;
_this._drCvaOnChange = function () { };
_this._drDatepickerClearSubscription = Subscription.EMPTY;
return _this;
}
MatDaterangepickerInputEnd_1 = MatDaterangepickerInputEnd;
Object.defineProperty(MatDaterangepickerInputEnd.prototype, "matDaterangepickerEnd", {
set: function (value) {
if (this._datepicker !== value) {
this.unregister();
this._datepicker = value;
value._registerInputRangeEnd(this);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MatDaterangepickerInputEnd.prototype, "_matDaterangepickerEnd", {
get: function () {
return this._datepicker;
},
enumerable: true,
configurable: true
});
MatDaterangepickerInputEnd.prototype.ngAfterViewInit = function () {
// Object.defineProperty(this, 'value', {
// set: function (value: D | null) {
// if(!this._matDaterangepickerEnd.applyButton){
// console.log('end '+value)
// return;
// }
// value = this._dateAdapter.deserialize(value);
// this._lastValueValid = !value || this._dateAdapter.isValid(value);
// value = this._getValidDateOrNull(value);
// const oldDate = this.value;
// this['_assignValue'](value);
// this['_formatValue'](value);
// if (!this._dateAdapter.sameDate(oldDate, value)) {
// this._valueChange.emit(value);
// }
// }
// })
};
MatDaterangepickerInputEnd.prototype.ngAfterContentInit = function () {
var _this = this;
if (this._datepicker) {
this._matDatepickerSubscription = this._matDaterangepickerEnd._selectedChangedRangeEnd.subscribe(function (selected) {
_this.value = selected;
_this._drCvaOnChange(selected);
_this._onTouched();
_this.dateInput.emit(new MatDatepickerInputEvent(_this, _this._drElementRef.nativeElement));
_this.dateChange.emit(new MatDatepickerInputEvent(_this, _this._drElementRef.nativeElement));
});
//runs every clear range end
this._drDatepickerClearSubscription = this._matDaterangepickerEnd._clearRangeEnd.subscribe(function () {
_this.value = null;
_this._drCvaOnChange(null);
});
}
};
MatDaterangepickerInputEnd.prototype.ngOnDestroy = function () {
_super.prototype.ngOnDestroy.call(this);
this.unregister();
this._matDatepickerSubscription.unsubscribe();
this._drDatepickerClearSubscription.unsubscribe();
};
// Implemented as part of ControlValueAccessor.
MatDaterangepickerInputEnd.prototype.registerOnChange = function (fn) {
this._drCvaOnChange = fn;
_super.prototype.registerOnChange.call(this, fn);
};
MatDaterangepickerInputEnd.prototype.unregister = function () {
if (this._matDaterangepickerEnd) {
this._matDaterangepickerEnd._unregisterInputRangeEnd(this);
}
};
var MatDaterangepickerInputEnd_1;
MatDaterangepickerInputEnd.ctorParameters = function () { return [
{ type: ElementRef },
{ type: DateAdapter, decorators: [{ type: Optional }] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAT_DATE_FORMATS,] }] },
{ type: MatFormField, decorators: [{ type: Optional }] }
]; };
__decorate([
Input()
], MatDaterangepickerInputEnd.prototype, "matDaterangepickerEnd", null);
MatDaterangepickerInputEnd = MatDaterangepickerInputEnd_1 = __decorate([
Directive({
selector: '[matDaterangepickerEnd]',
providers: [
SG_DATEPICKER_VALUE_ACCESSOR,
SG_DATEPICKER_VALIDATORS,
{ provide: MAT_INPUT_VALUE_ACCESSOR, useExisting: MatDaterangepickerInputEnd_1 },
],
host: {
'[attr.aria-haspopup]': 'true',
'[attr.aria-owns]': '(_datepicker?.opened && _datepicker.id) || null',
'[attr.min]': 'min ? _dateAdapter.toIso8601(min) : null',
'[attr.max]': 'max ? _dateAdapter.toIso8601(max) : null',
'[disabled]': 'disabled',
'(input)': '_onInput($event.target.value)',
'(change)': '_onChange()',
'(blur)': '_onBlur()',
'(keydown)': '_onKeydown($event)',
},
exportAs: 'MatDaterangepickerInputEnd',
}),
__param(1, Optional()),
__param(2, Optional()), __param(2, Inject(MAT_DATE_FORMATS)),
__param(3, Optional())
], MatDaterangepickerInputEnd);
return MatDaterangepickerInputEnd;
}(MatDatepickerInput));
/*
RANGE: Most of the code is redundant and hera as inheritance boilerplate.
The added/edited code adds logic for handling range / non range mode.
Additionaly, in range mode it will apply logic to mark the dates within the active month
that are within the range.
There are 3 range states for a month view, set by the combination of "_rangable" and "_allInRange":
- Not rangable (single value datepicker OR active month not in range) - _rangable = False
- Rangable but not all (active month is partially in range) - _rangable = True
- All In Range (active month is in range, start/end dates before/after this month) - _rangable = True & _allInRange = True
*/
var MatDaterangeMonthView = /** @class */ (function (_super) {
__extends(MatDaterangeMonthView, _super);
function MatDaterangeMonthView() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.selectedRangeEndChange = new EventEmitter();
_this._createDate = function (date) {
var selectedYear = _this._dateAdapter.getYear(_this.activeDate);
var selectedMonth = _this._dateAdapter.getMonth(_this.activeDate);
return new Date(selectedYear, selectedMonth, date);
};
return _this;
}
Object.defineProperty(MatDaterangeMonthView.prototype, "selectedRangeEnd", {
get: function () {
return this._selectedRangeEnd;
},
set: function (value) {
this._selectedRangeEnd = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
this._selectedRangeEndDate = this._getDateInCurrentMonth(this._selectedRangeEnd);
},
enumerable: true,
configurable: true
});
Object.defineProperty(MatDaterangeMonthView.prototype, "_allInRange", {
get: function () {
if (!this.range || !this.activeDate || !this.selectedRangeEnd || !this.selected) {
return false;
}
else {
var daysInMonth = this._dateAdapter.getNumDaysInMonth(this.activeDate);
var startDate = this.createDate(1);
var endDate = this.createDate(daysInMonth);
return this._dateAdapter.compareDate(this.selected, startDate) < 0 &&
this._dateAdapter.compareDate(this.selectedRangeEnd, endDate) > 0;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MatDaterangeMonthView.prototype, "_rangable", {
get: function () {
if (!this.range || !this._weeks) {
return false;
}
else {
var daysInMonth = this._dateAdapter.getNumDaysInMonth(this.activeDate);
var startDate = this.createDate(1);
var endDate = this.createDate(daysInMonth);
if (this.selectedRangeEnd < startDate) {
return false;
}
if (this.selected > endDate) {
return false;
}
return true;
}
},
enumerable: true,
configurable: true
});
MatDaterangeMonthView.prototype._init = function () {
this._selectedRangeEndDate = this._getDateInCurrentMonth(this.selectedRangeEnd);
_super.prototype._init.call(this);
};
MatDaterangeMonthView.prototype._dateSelected = function (date) {
return __awaiter(this, void 0, void 0, function () {
var selectedDate, year, month, swap;
return __generator(this, function (_a) {
if (!this.range) {
_super.prototype._dateSelected.call(this, date);
}
else {
if (!this.selected || this.selectedRangeEnd) {
if (this._selectedRangeEnd) {
this._dateSelectedRangeEnd(null);
}
_super.prototype._dateSelected.call(this, date);
}
else {
if (date === null) {
this._dateSelectedRangeEnd(null);
}
else {
selectedDate = this.createDate(date);
if (selectedDate < this.selected) {
year = this._dateAdapter.getYear(this.selected);
month = this._dateAdapter.getMonth(this.selected);
swap = this._dateAdapter.getDate(this.selected);
_super.prototype._dateSelected.call(this, date);
this._dateSelectedRangeEnd(swap, year, month);
}
else {
this._dateSelectedRangeEnd(date);
}
}
}
}
return [2 /*return*/];
});
});
};
MatDaterangeMonthView.prototype._dateSelectedRangeEnd = function (date, year, month) {
if (date === null) {
this.selectedRangeEndChange.emit(null);
}
else if (this._selectedRangeEndDate != date) {
var selectedDate = void 0;
if (year && month) {
selectedDate = this._dateAdapter.createDate(year, month, date);
}
else {
selectedDate = this.createDate(date);
}
this.selectedRangeEndChange.emit(selectedDate);
this._userSelection.emit();
}
};
MatDaterangeMonthView.prototype.createDate = function (date) {
var selectedYear = this._dateAdapter.getYear(this.activeDate);
var selectedMonth = this._dateAdapter.getMonth(this.activeDate);
return this._dateAdapter.createDate(selectedYear, selectedMonth, date);
};
MatDaterangeMonthView.prototype.getSelectedDate = function () {
if (!this.selected)
return null;
var selectedYear = this._dateAdapter.getYear(this.selected);
var selectedMonth = this._dateAdapter.getMonth(this.selected);
var selectedDate = this._dateAdapter.getDate(this.selected);
return new Date(selectedYear, selectedMonth, selectedDate);
};
MatDaterangeMonthView.prototype.getSelectedRangeEndDate = function () {
if (!this.selectedRangeEnd)
return null;
var selectedYear = this._dateAdapter.getYear(this.selectedRangeEnd);
var selectedMonth = this._dateAdapter.getMonth(this.selectedRangeEnd);
var selectedDate = this._dateAdapter.getDate(this.selectedRangeEnd);
return new Date(selectedYear, selectedMonth, selectedDate);
};
__decorate([
Input()
], MatDaterangeMonthView.prototype, "range", void 0);
__decorate([
Input()
], MatDaterangeMonthView.prototype, "view", void 0);
__decorate([
Input()
], MatDaterangeMonthView.prototype, "setHoverCells", void 0);
__decorate([
Input()
], MatDaterangeMonthView.prototype, "clearBody", void 0);
__decorate([
Input()
], MatDaterangeMonthView.prototype, "selectedRangeEnd", null);
__decorate([
Output()
], MatDaterangeMonthView.prototype, "selectedRangeEndChange", void 0);
MatDaterangeMonthView = __decorate([
Component({
selector: 'mat-daterange-month-view',
template: "<!-- \n RANGE: Most of the code is redundant and hera as inheritance boilerplate.\n \n The 3 attributes in the middle are the additional bindings to the template.\n They notify the body:\n - Are we in range mode ([range])\n - Are all the dates in range ([allInRange])\n this happens when the start date is before the current month and the end is after it.\n - The value marking the end of the range ([selectedRangeEndValue])\n\n ADDED LOC ~3\n -->\n\n<table class=\"mat-calendar-table\">\n <thead class=\"mat-calendar-table-header\">\n <tr><th *ngFor=\"let day of _weekdays\" [attr.aria-label]=\"day.long\">{{day.narrow}}</th></tr>\n <tr><th class=\"mat-calendar-table-header-divider\" colspan=\"7\" aria-hidden=\"true\"></th></tr>\n </thead>\n <tbody mat-daterange-calendar-body\n [view]=\"view\"\n [label]=\"_monthLabel\"\n [rows]=\"_weeks\"\n [todayValue]=\"_todayDate\"\n [selectedValue]=\"_selectedDate\"\n\n [selectedRangeEndValue]=\"_selectedRangeEndDate\"\n [allInRange]=\"_allInRange\"\n [range]=\"_rangable\"\n [createDate]=\"_createDate\"\n [dateAdapter]=\"_dateAdapter\"\n [selected]=\"getSelectedDate()\"\n [selectedRangeEnd]=\"getSelectedRangeEndDate()\"\n [setHoverCells]=\"setHoverCells\"\n [clearBody]=\"clearBody\"\n [labelMinRequiredCells]=\"3\"\n [activeCell]=\"_dateAdapter.getDate(activeDate) - 1\"\n (selectedValueChange)=\"_dateSelected($event)\" \n (keydown)=\"_handleCalendarBodyKeydown($event)\">\n </tbody>\n</table>\n",
exportAs: 'matMonthView',
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
changeDetection: ChangeDetectionStrategy.OnPush
})
], MatDaterangeMonthView);
return MatDaterangeMonthView;
}(MatMonthView));
/*
RANGE: Most of the code is redundant and hera as inheritance boilerplate.
The relevant code is marked with a comment.
*/
var MatDaterangeCalendarBody = /** @class */ (function (_super) {
__extends(MatDaterangeCalendarBody, _super);
function MatDaterangeCalendarBody() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.hoverSubscription = Subscription.EMPTY;
_this.clearBodySubscription = Subscription.EMPTY;
return _this;
}
MatDaterangeCalendarBody.prototype.ngOnInit = function () {
var _this = this;
this.hoverSubscription = this.setHoverCells.subscribe(function (tmpDate) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (!tmpDate || !this.selected || this.selectedRangeEnd || (this.selected && this.selectedRangeEnd))
return [2 /*return*/];
this._doHoverCells(tmpDate);
return [2 /*return*/];
});
}); });
this.clearBodySubscription = this.clearBody.subscribe(function (clear) {
if (clear) {
_this._doHoverCells(null, clear);
}
});
};
MatDaterangeCalendarBody.prototype._cellClass = function (date) {
if (!this.selected || !this.selectedRangeEnd)
return;
var startDate = this.selected.getTime();
var endDate = this.selectedRangeEnd.getTime();
var cellDate = this.createDate(date).getTime();
return {
'mat-daterange-calendar-body-in-range': cellDate >= startDate && cellDate <= endDate && startDate !== endDate,
'mat-daterange-calendar-body-range-start': cellDate === startDate && startDate !== endDate,
'mat-daterange-calendar-body-range-end': cellDate === endDate && startDate !== endDate
};
};
MatDaterangeCalendarBody.prototype._inRange = function (date) {
// if (this.range) {
// if (this.allInRange) {
// return true;
// }
// if (this.selectedValue && !this.selectedRangeEndValue) {
// return date >= this.selectedValue;
// }
// if (this.selectedRangeEndValue && !this.selectedValue) {
// return date <= this.selectedRangeEndValue;
// }
// return date >= this.selectedValue && date <= this.selectedRangeEndValue;
// }
};
MatDaterangeCalendarBody.prototype._onHoverCell = function (tmpDate) {
if (this.selectedRangeEndValue)
return;
this.setHoverCells.next(this.createDate(tmpDate));
};
MatDaterangeCalendarBody.prototype._doHoverCells = function (tmpDate, clear) {
var _this = this;
var _a;
var startDate = (_a = this.selected) === null || _a === void 0 ? void 0 : _a.getTime();
var endTempDate = tmpDate === null || tmpDate === void 0 ? void 0 : tmpDate.getTime();
this.rows.map(function (row, r) {
var rowElm = _this.rowsElms.toArray()[r];
var hasLabel = false;
row.map(function (cell, c) {
var cellElm = rowElm.nativeElement.cells[hasLabel ? c + 1 : c];
if (cellElm.classList.contains('mat-calendar-body-label')) {
hasLabel = true;
cellElm = rowElm.nativeElement.cells[c + 1];
}
cellElm.classList.remove('mat-daterange-calendar-body-in-range');
cellElm.classList.remove('mat-daterange-calendar-body-range-end');
cellElm.classList.remove('mat-daterange-calendar-body-range-start');
if (clear)
return;
var inRange = _this._inRangeTemp(cell.value, startDate, endTempDate, cellElm);
});
});
};
MatDaterangeCalendarBody.prototype._inRangeTemp = function (date, startDate, endTempDate, cellElm) {
var cellDate = this.createDate(date).getTime();
if (endTempDate >= startDate) {
if (endTempDate !== startDate) {
if (cellDate === startDate) {
cellElm.classList.add('mat-daterange-calendar-body-in-range');
cellElm.classList.add('mat-daterange-calendar-body-range-start');
}
if (cellDate === endTempDate) {
cellElm.classList.add('mat-daterange-calendar-body-in-range');
cellElm.classList.add('mat-daterange-calendar-body-range-end');
}
}
if (cellDate > startDate && cellDate < endTempDate) {
cellElm.classList.add('mat-daterange-calendar-body-in-range');
return true;
}
return false;
}
else {
if (endTempDate !== startDate) {
if (cellDate === startDate) {
cellElm.classList.add('mat-daterange-calendar-body-in-range');
cellElm.classList.add('mat-daterange-calendar-body-range-end');
}
if (cellDate === endTempDate) {
cellElm.classList.add('mat-daterange-calendar-body-in-range');
cellElm.classList.add('mat-daterange-calendar-body-range-start');
}
}
if (cellDate < startDate && cellDate > endTempDate) {
cellElm.classList.add('mat-daterange-calendar-body-in-range');
return true;
}
return false;
}
};
MatDaterangeCalendarBody.prototype.ngOnDestroy = function () {
this.hoverSubscription.unsubscribe();
this.clearBodySubscription.unsubscribe();
};
__decorate([
Input()
], MatDaterangeCalendarBody.prototype, "range", void 0);
__decorate([
Input()
], MatDaterangeCalendarBody.prototype, "allInRange", void 0);
__decorate([
Input()