nm-fromtodatepicker
src/app/shared/widgets/imarket/from-to-datepicker-widget/from-to-datepicker-widget.component.ts
selector | nm-fromtodatepicker |
styleUrls | from-to-datepicker-widget.component.scss |
templateUrl | ./from-to-datepicker-widget.component.html |
Widget inputs |
Widget outputs |
Properties |
|
Methods |
constructor(dateAdapter: DateAdapter
|
||||||||||||||||||||||||
Parameters :
|
clearField | ||||||
clearField(field: string)
|
||||||
Parameters :
Returns :
void
|
Protected configureWidget | ||||||
configureWidget(configuration: WidgetConfig
|
||||||
Decorators : WidgetConfigure
|
||||||
Parameters :
Returns :
void
|
detectError |
detectError()
|
Returns :
void
|
formatDate |
formatDate(date: Date, dateType: string)
|
Returns :
string
|
getValidations | ||||
getValidations(validations: )
|
||||
Parameters :
Returns :
{}
|
ngAfterViewInit |
ngAfterViewInit()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
validateAndEmitFromDate | ||||
validateAndEmitFromDate(fromDate: )
|
||||
Parameters :
Returns :
void
|
validateAndEmitToDate | ||||
validateAndEmitToDate(toDate: )
|
||||
Parameters :
Returns :
void
|
Public addLabel |
addLabel:
|
Type : boolean
|
Public configuration |
configuration:
|
Type : WidgetConfig<FromToDatePickerWidgetConfiguration>
|
Decorators : WidgetConfiguration
|
Public dateAndTimePicker |
dateAndTimePicker:
|
Type : boolean
|
Public dateTimeForm |
dateTimeForm:
|
Type : FormGroup
|
Private defaultFromDate |
defaultFromDate:
|
Type : any
|
Private defaultFromDateSubject |
defaultFromDateSubject:
|
Type : Subject<any>
|
Default value : new Subject<any>()
|
Decorators : WidgetInput
|
Sets a default value for the from date |
Private defaultToDate |
defaultToDate:
|
Type : any
|
Private defaultToDateSubject |
defaultToDateSubject:
|
Type : Subject<any>
|
Default value : new Subject<any>()
|
Decorators : WidgetInput
|
Sets a default value for the to date |
Public feDateFormat |
feDateFormat:
|
Type : boolean
|
Public firstDayOfWeek |
firstDayOfWeek:
|
Type : number
|
Public floatLabel |
floatLabel:
|
Type : string
|
Private fromDateEntry |
fromDateEntry:
|
Type : LocalStorageEntry
|
Public fromDateStartsAt |
fromDateStartsAt:
|
Type : Date
|
Default value : new Date()
|
Public fromLabelName |
fromLabelName:
|
Type : string
|
Public fromPlaceholder |
fromPlaceholder:
|
Type : string
|
Public ignoreTime |
ignoreTime:
|
Type : boolean
|
Public labelWidth |
labelWidth:
|
Type : string
|
Public maxFromDate |
maxFromDate:
|
Type : Date
|
Public maxFromDateInput |
maxFromDateInput:
|
Type : Subject<Date>
|
Default value : new Subject<Date>()
|
Decorators : WidgetInput
|
Sets a maximum date value to the from date picker |
Public maxToDate |
maxToDate:
|
Type : Date
|
Public maxToDateInput |
maxToDateInput:
|
Type : Subject<Date>
|
Default value : new Subject<Date>()
|
Decorators : WidgetInput
|
Sets a maximum date value to the to date picker |
Public minFromDate |
minFromDate:
|
Type : Date
|
Public minFromDateInput |
minFromDateInput:
|
Type : Subject<Date>
|
Default value : new Subject<Date>()
|
Decorators : WidgetInput
|
Sets a minimum date value to the from date picker |
Public minToDate |
minToDate:
|
Type : Date
|
Public minToDateInput |
minToDateInput:
|
Type : Subject<Date>
|
Default value : new Subject<Date>()
|
Decorators : WidgetInput
|
Sets a minimum date value to the to date picker |
Private outputFromDate |
outputFromDate:
|
Type : ReplaySubject<any>
|
Default value : new ReplaySubject<any>(1)
|
Decorators : WidgetOutput
|
Outputs from date value whenever changed |
Private outputToDate |
outputToDate:
|
Type : ReplaySubject<any>
|
Default value : new ReplaySubject<any>(1)
|
Decorators : WidgetOutput
|
Outputs from date value whenever changed |
Public pickerDisable |
pickerDisable:
|
Type : boolean
|
Default value : false
|
Public pickerHide |
pickerHide:
|
Type : boolean
|
Default value : false
|
Public pickerRightMargin |
pickerRightMargin:
|
Type : string
|
Public pickerWidth |
pickerWidth:
|
Type : string
|
Private resetChannel |
resetChannel:
|
Type : Subject<any>
|
Default value : new Subject<any>()
|
Decorators : WidgetInput
|
When fired resets both date pickers and their local storage entries |
Private toDateEntry |
toDateEntry:
|
Type : LocalStorageEntry
|
Public toDateStartsAt |
toDateStartsAt:
|
Type : Date
|
Default value : new Date()
|
Public toLabelName |
toLabelName:
|
Type : string
|
Public toPlaceholder |
toPlaceholder:
|
Type : string
|
Private unsubscribe |
unsubscribe:
|
Default value : NgUnsubscribe.create()
|
Private validations |
validations:
|
Type : any
|
import { Component, AfterViewInit, OnDestroy } from "@angular/core";
import { FormControl, FormGroup, FormBuilder } from "@angular/forms";
import { ReplaySubject, Subject } from "rxjs";
import { getOrDefault, WidgetConfig } from "../../widget.configuration";
import {
WidgetComponent,
WidgetConfiguration,
WidgetConfigure,
WidgetInput,
WidgetOutput,
} from "../../widget.metadata";
import { BaseConfiguration } from "../../widgetframe/widgetframe.component";
import { CurrentLocaleService } from "../../../components/i18n/currentLocale.service";
import {
DeletionMode,
Scope,
} from "../../../components/local-storage/local-storage-constants";
import {
LocalStorageEntry,
LocalStorageService,
} from "../../../components/local-storage/local-storage.service";
import { NgUnsubscribe } from "../../../ng-unsubscribe";
import { DateAdapter } from "@angular/material/core";
import { TranslateService } from "@ngx-translate/core";
import { OwlDateTimeIntl, DateTimeAdapter } from "ng-pick-datetime";
import { takeUntil } from "rxjs/operators";
import { validateWithMandatoryFields, validate } from "./date-range.validator";
export interface FromToDatePickerWidgetConfiguration extends BaseConfiguration {
/**
* A boolean, that if true, adds a label before the from to date picker @default(false)
*/
addLabel?: boolean;
/**
* A localized property key that shows a label before the from date picker
*/
fromLabelName?: string;
/**
* A localized property key that shows a label before the to date picker
*/
toLabelName?: string;
/**
* Sets a specific width for the date picker
*/
pickerWidth?: string;
/**
* Sets a specific width for the date picker's label
*/
labelWidth?: string;
/**
* A localized property key that shows a placeholder for the from date picker
*/
fromPlaceholder?: string;
/**
* A localized property key that shows a placeholder for the to date picker
*/
toPlaceholder?: string;
/**
* Sets a floating label to both date pickers
*/
floatLabel?: string;
/**
* A boolean, that ignores setting time for the date picker, sets both with 00:00:00, otherwise from date is set with 00:00:00 and to date is set with 24:59:59 @default(false)
*/
ignoreTime?: boolean;
/**
* A boolean, that enables both setting of date and time in the date picker @default(false)
*/
dateAndTimePicker?: boolean;
/**
* A boolean, that enables output of date formatted relative to timezone @default(true)
*/
feDateFormat?: boolean;
/**
* Sets validations for date picker
*/
validations?: any;
/**
* Sets first day of week shown in date picker, @default(1) which shows monday
*/
firstDayOfWeek?: number;
/**
* Sets margin between both date pickers
*/
pickerRightMargin?: string;
}
@WidgetComponent("nm-fromtodatepicker")
@Component({
selector: "nm-fromtodatepicker",
templateUrl: "./from-to-datepicker-widget.component.html",
styleUrls: ["./from-to-datepicker-widget.component.scss"],
})
export class FromToDatePickerWidgetComponent
implements AfterViewInit, OnDestroy {
public dateTimeForm: FormGroup;
public addLabel: boolean;
public labelWidth: string;
public pickerWidth: string;
public fromLabelName: string;
public toLabelName: string;
public fromPlaceholder: string;
public toPlaceholder: string;
public floatLabel: string;
public dateAndTimePicker: boolean;
public feDateFormat: boolean;
private validations: any;
public minFromDate: Date;
public maxFromDate: Date;
public minToDate: Date;
public maxToDate: Date;
public ignoreTime: boolean;
private defaultFromDate: any;
private defaultToDate: any;
public firstDayOfWeek: number;
public pickerRightMargin: string;
public pickerDisable: boolean = false;
public pickerHide: boolean = false;
private fromDateEntry: LocalStorageEntry;
private toDateEntry: LocalStorageEntry;
public fromDateStartsAt: Date = new Date();
public toDateStartsAt: Date = new Date();
private unsubscribe = NgUnsubscribe.create();
@WidgetConfiguration()
public configuration: WidgetConfig<FromToDatePickerWidgetConfiguration>;
/**
* A boolean input, when true it hides the date picker @default(false)
*/
@WidgetInput("datePickerHide")
private datePickerHide: Subject<boolean> = new Subject<boolean>();
/**
* When fired resets both date pickers and their local storage entries
*/
@WidgetInput("reset")
private resetChannel: Subject<any> = new Subject<any>();
/**
* Outputs from date value whenever changed
*/
@WidgetOutput("outputFromDate")
private outputFromDate: ReplaySubject<any> = new ReplaySubject<any>(1);
/**
* Outputs from date value whenever changed
*/
@WidgetOutput("outputToDate")
private outputToDate: ReplaySubject<any> = new ReplaySubject<any>(1);
/**
* Outputs a boolean, which shows if an error occurred in the date form
*/
@WidgetOutput("errorDetected")
private errorDetected: ReplaySubject<boolean> = new ReplaySubject<boolean>(1);
/**
* Sets a default value for the from date
*/
@WidgetInput("defaultFromDate")
private defaultFromDateSubject: Subject<any> = new Subject<any>();
/**
* Sets a default value for the to date
*/
@WidgetInput("defaultToDate")
private defaultToDateSubject: Subject<any> = new Subject<any>();
/**
* When fired resets both date pickers to their default values
*/
@WidgetInput("resetToDefault")
private resetToDefaultChannel: Subject<any> = new Subject<any>();
/**
* A boolean input, when true it disables the date picker @default(false)
*/
@WidgetInput("disabled")
public disabled: Subject<boolean> = new Subject<boolean>();
/**
* Sets a minimum date value to the from date picker
*/
@WidgetInput("minFromDate")
public minFromDateInput: Subject<Date> = new Subject<Date>();
/**
* Sets a maximum date value to the from date picker
*/
@WidgetInput("maxFromDate")
public maxFromDateInput: Subject<Date> = new Subject<Date>();
/**
* Sets a minimum date value to the to date picker
*/
@WidgetInput("minToDate")
public minToDateInput: Subject<Date> = new Subject<Date>();
/**
* Sets a maximum date value to the to date picker
*/
@WidgetInput("maxToDate")
public maxToDateInput: Subject<Date> = new Subject<Date>();
@WidgetConfigure()
protected configureWidget(
configuration: WidgetConfig<FromToDatePickerWidgetConfiguration>
) {
this.addLabel = getOrDefault(
this.configuration.configuration.addLabel,
false
);
this.fromLabelName = this.configuration.configuration.fromLabelName;
this.toLabelName = this.configuration.configuration.toLabelName;
this.pickerWidth = this.configuration.configuration.pickerWidth;
this.labelWidth = this.configuration.configuration.labelWidth;
this.fromPlaceholder = this.configuration.configuration.fromPlaceholder;
this.toPlaceholder = this.configuration.configuration.toPlaceholder;
this.floatLabel = this.configuration.configuration.floatLabel;
this.pickerRightMargin = this.configuration.configuration.pickerRightMargin;
this.ignoreTime = getOrDefault(
this.configuration.configuration.ignoreTime,
false
);
this.dateAndTimePicker = getOrDefault(
this.configuration.configuration.dateAndTimePicker,
false
);
this.feDateFormat = getOrDefault(
this.configuration.configuration.feDateFormat,
true
);
this.validations = getOrDefault(
this.configuration.configuration.validations,
null
);
this.firstDayOfWeek = getOrDefault(
this.configuration.configuration.firstDayOfWeek,
1
);
if (configuration.configuration["localstorage-fromdate"]) {
this.fromDateEntry = this.localStorageService.getLocalStorageEntry(
configuration.configuration["localstorage-fromdate"],
Scope.GLOBAL,
DeletionMode.NEVER
);
}
if (configuration.configuration["localstorage-todate"]) {
this.toDateEntry = this.localStorageService.getLocalStorageEntry(
configuration.configuration["localstorage-todate"],
Scope.GLOBAL,
DeletionMode.NEVER
);
}
this.fromDateStartsAt.setHours(0, 0, 0, 0);
this.toDateStartsAt.setHours(23, 59, 59, 999);
this.dateTimeForm = this.formBuilder.group(
{
fromDate: new FormControl(null),
toDate: new FormControl(null),
},
{
validators: this.getValidations(this.validations),
}
);
this.datePickerHide
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((datePickerHide) => {
this.pickerHide = datePickerHide;
});
this.currentLocaleService
.getCurrentLocale()
.pipe(takeUntil(this.unsubscribe))
.subscribe((locale) => {
this.dateAdapter.setLocale(locale);
this.dateTimeAdapter.setLocale(locale);
this.translateService
.get("button.cancel")
.subscribe(
(translation) => (this.owlDateTimeIntl.cancelBtnLabel = translation)
);
this.translateService
.get("button.accept")
.subscribe(
(translation) => (this.owlDateTimeIntl.setBtnLabel = translation)
);
});
this.resetChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((reset) => {
if (this.fromDateEntry) {
this.fromDateEntry.clear();
}
if (this.toDateEntry) {
this.toDateEntry.clear();
}
this.dateTimeForm.get("fromDate").markAsUntouched();
this.dateTimeForm.get("toDate").markAsUntouched();
this.dateTimeForm.setValue({
toDate: null,
fromDate: null,
});
});
this.defaultFromDateSubject
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((date) => {
this.defaultFromDate = date;
if (
!(
this.fromDateEntry &&
this.fromDateEntry.exists() &&
this.fromDateEntry.value
)
) {
this.dateTimeForm.patchValue({ fromDate: date });
if (this.fromDateEntry) {
this.fromDateEntry.value = date ? date.toISOString() : "";
}
this.detectError();
}
});
this.defaultToDateSubject
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((date) => {
this.defaultToDate = date;
if (
!(
this.toDateEntry &&
this.toDateEntry.exists() &&
this.toDateEntry.value
)
) {
this.dateTimeForm.patchValue({ toDate: date });
if (this.toDateEntry) {
this.toDateEntry.value = date ? date.toISOString() : "";
}
this.detectError();
}
});
this.resetToDefaultChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((reset) => {
this.dateTimeForm.get("toDate").markAsUntouched();
this.dateTimeForm.get("fromDate").markAsUntouched();
this.dateTimeForm.setValue({
toDate: this.defaultToDate,
fromDate: this.defaultFromDate,
});
});
this.disabled.pipe(takeUntil(this.unsubscribe)).subscribe((data) => {
this.pickerDisable = data;
});
this.minFromDateInput
.pipe(takeUntil(this.unsubscribe))
.subscribe((minFromDate) => {
this.minFromDate = minFromDate;
});
this.maxFromDateInput
.pipe(takeUntil(this.unsubscribe))
.subscribe((maxFromDate) => {
this.maxFromDate = maxFromDate;
});
this.minToDateInput
.pipe(takeUntil(this.unsubscribe))
.subscribe((minToDate) => {
this.minToDate = minToDate;
});
this.maxToDateInput
.pipe(takeUntil(this.unsubscribe))
.subscribe((maxToDate) => {
this.maxToDate = maxToDate;
});
}
constructor(
private dateAdapter: DateAdapter<any>,
private localStorageService: LocalStorageService,
private formBuilder: FormBuilder,
private translateService: TranslateService,
private owlDateTimeIntl: OwlDateTimeIntl,
private dateTimeAdapter: DateTimeAdapter<any>,
private currentLocaleService: CurrentLocaleService
) {}
ngAfterViewInit() {
let fromDateInput: Date = null;
let toDateInput: Date = null;
if (
this.fromDateEntry &&
this.fromDateEntry.exists() &&
this.fromDateEntry.value != ""
) {
fromDateInput = new Date(this.fromDateEntry.value);
}
if (
this.toDateEntry &&
this.toDateEntry.exists() &&
this.toDateEntry.value != ""
) {
toDateInput = new Date(this.toDateEntry.value);
}
this.dateTimeForm.setValue({
toDate: toDateInput,
fromDate: fromDateInput,
});
this.detectError();
if (fromDateInput) {
this.outputFromDate.next(this.formatDate(fromDateInput, "from"));
this.fromDateStartsAt = fromDateInput;
} else {
this.outputFromDate.next(null);
}
if (toDateInput) {
this.outputToDate.next(this.formatDate(toDateInput, "to"));
this.toDateStartsAt = toDateInput;
} else {
this.outputToDate.next(null);
}
}
getValidations(validations) {
let validationFunction = [];
validationFunction.push(validate);
if (validations && validations.mandatory) {
validationFunction.push(validateWithMandatoryFields);
}
return validationFunction;
}
validateAndEmitFromDate(fromDate) {
this.detectError();
if (fromDate) {
if (this.fromDateEntry) {
this.fromDateEntry.value = new Date(fromDate).toISOString();
}
this.fromDateStartsAt = new Date(fromDate);
this.outputFromDate.next(this.formatDate(new Date(fromDate), "from"));
} else {
if (this.fromDateEntry && this.fromDateEntry.exists()) {
this.fromDateEntry.clear();
}
this.outputFromDate.next(null);
}
}
validateAndEmitToDate(toDate) {
this.detectError();
if (toDate) {
if (this.toDateEntry) {
this.toDateEntry.value = new Date(toDate).toISOString();
}
this.toDateStartsAt = new Date(toDate);
this.outputToDate.next(this.formatDate(new Date(toDate), "to"));
} else {
if (this.toDateEntry && this.toDateEntry.exists()) {
this.toDateEntry.clear();
}
this.outputToDate.next(null);
}
}
formatDate(date: Date, dateType: string): string {
if (!this.dateAndTimePicker) {
if (this.ignoreTime || dateType === "from") {
date.setHours(0, 0, 0, 0);
} else {
date.setHours(23, 59, 59, 999);
}
return this.feDateFormat
? new Date(date.getTime() - date.getTimezoneOffset() * 60000).toJSON()
: new Date(date.getTime()).toJSON();
}
return date.toJSON();
}
detectError() {
this.dateTimeForm.updateValueAndValidity();
if (this.dateTimeForm.errors) {
this.errorDetected.next(true);
} else {
this.errorDetected.next(false);
}
}
clearField(field: string) {
this.dateTimeForm.controls[field].setValue(null);
if (field === "fromDate") {
this.fromDateStartsAt.setHours(0, 0, 0, 0);
this.validateAndEmitFromDate(null);
} else {
this.toDateStartsAt.setHours(23, 59, 59, 999);
this.validateAndEmitToDate(null);
}
}
ngOnDestroy() {
this.unsubscribe.destroy();
}
}
<form *ngIf="!pickerHide" [formGroup]="dateTimeForm">
<div
*ngIf="addLabel"
[style.width]="labelWidth"
class="nm-from-to-datepicker__label"
>
<nm-ellipsis [content]="fromLabelName | translate"></nm-ellipsis>
</div>
<div
class="nm-from-to-datepicker__wrapper"
[style.width]="pickerWidth"
[style.margin-right]="pickerRightMargin"
>
<mat-form-field [floatLabel]="floatLabel" [style.width]="'100%'">
<input
autocomplete="off"
matInput
formControlName="fromDate"
[owlDateTime]="fromdatetimepicker"
(ngModelChange)="validateAndEmitFromDate($event)"
[readonly]="true"
placeholder="{{ fromPlaceholder | translate }}"
[nmAutofocus]="false"
[ngClass]="{ 'nm-from-to-datepicker__input--disabled': pickerDisable }"
[min]="minFromDate"
[max]="maxFromDate"
/>
<button
mat-icon-button
primary
matSuffix
*ngIf="dateTimeForm?.get('fromDate').value && !(disabled | async)"
(click)="clearField('fromDate')"
>
<mat-icon class="fade-in">close</mat-icon>
</button>
<button
mat-button
matSuffix
mat-icon-button
aria-label="date_range"
[owlDateTimeTrigger]="fromdatetimepicker"
(click)="fromdatetimepicker.open()"
[disabled]="pickerDisable"
>
<mat-icon>event</mat-icon>
</button>
</mat-form-field>
<owl-date-time
#fromdatetimepicker
[pickerType]="dateAndTimePicker ? 'both' : 'calendar'"
[firstDayOfWeek]="firstDayOfWeek"
[startAt]="fromDateStartsAt"
></owl-date-time>
<ng-container *ngIf="dateTimeForm.errors?.fromDateEmpty">
<mat-error class="nm-from-to-datepicker__dateValidation"
>{{ "imarket-from-date-empty-error" | translate }}
</mat-error>
</ng-container>
</div>
<div
*ngIf="addLabel"
[style.width]="labelWidth"
class="nm-from-to-datepicker__label"
>
<nm-ellipsis [content]="toLabelName | translate"></nm-ellipsis>
</div>
<div class="nm-from-to-datepicker__wrapper" [style.width]="pickerWidth">
<mat-form-field [floatLabel]="floatLabel" [style.width]="'100%'">
<input
autocomplete="off"
matInput
formControlName="toDate"
[owlDateTime]="todatetimepicker"
(ngModelChange)="validateAndEmitToDate($event)"
[readonly]="true"
placeholder="{{ toPlaceholder | translate }}"
[nmAutofocus]="false"
[ngClass]="{ 'nm-from-to-datepicker__input--disabled': pickerDisable }"
[min]="minToDate"
[max]="maxToDate"
/>
<button
mat-icon-button
primary
matSuffix
*ngIf="dateTimeForm?.get('toDate').value && !(disabled | async)"
(click)="clearField('toDate')"
>
<mat-icon class="fade-in">close</mat-icon>
</button>
<button
mat-button
matSuffix
mat-icon-button
aria-label="date_range"
[owlDateTimeTrigger]="todatetimepicker"
(click)="todatetimepicker.open()"
[disabled]="pickerDisable"
>
<mat-icon>event</mat-icon>
</button>
</mat-form-field>
<owl-date-time
#todatetimepicker
[pickerType]="dateAndTimePicker ? 'both' : 'calendar'"
[firstDayOfWeek]="firstDayOfWeek"
[startAt]="toDateStartsAt"
></owl-date-time>
<ng-container *ngIf="dateTimeForm.errors?.incorrect">
<mat-error class="nm-from-to-datepicker__dateValidation">{{
"imarket-date-error" | translate
}}</mat-error>
</ng-container>
<ng-container *ngIf="dateTimeForm.errors?.toDateEmpty">
<mat-error class="nm-from-to-datepicker__dateValidation">{{
"imarket-to-date-empty-error" | translate
}}</mat-error>
</ng-container>
</div>
</form>