src/app/shared/widgets/imarket/from-to-datepicker-widget/from-to-datepicker-widget.component.ts
Properties |
|
addLabel |
addLabel:
|
Type : boolean
|
Optional |
A boolean, that if true, adds a label before the from to date picker @default(false) |
dateAndTimePicker |
dateAndTimePicker:
|
Type : boolean
|
Optional |
A boolean, that enables both setting of date and time in the date picker @default(false) |
feDateFormat |
feDateFormat:
|
Type : boolean
|
Optional |
A boolean, that enables output of date formatted relative to timezone @default(true) |
firstDayOfWeek |
firstDayOfWeek:
|
Type : number
|
Optional |
Sets first day of week shown in date picker, @default(1) which shows monday |
floatLabel |
floatLabel:
|
Type : string
|
Optional |
Sets a floating label to both date pickers |
fromLabelName |
fromLabelName:
|
Type : string
|
Optional |
A localized property key that shows a label before the from date picker |
fromPlaceholder |
fromPlaceholder:
|
Type : string
|
Optional |
A localized property key that shows a placeholder for the from date picker |
ignoreTime |
ignoreTime:
|
Type : boolean
|
Optional |
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) |
labelWidth |
labelWidth:
|
Type : string
|
Optional |
Sets a specific width for the date picker's label |
pickerRightMargin |
pickerRightMargin:
|
Type : string
|
Optional |
Sets margin between both date pickers |
pickerWidth |
pickerWidth:
|
Type : string
|
Optional |
Sets a specific width for the date picker |
toLabelName |
toLabelName:
|
Type : string
|
Optional |
A localized property key that shows a label before the to date picker |
toPlaceholder |
toPlaceholder:
|
Type : string
|
Optional |
A localized property key that shows a placeholder for the to date picker |
validations |
validations:
|
Type : any
|
Optional |
Sets validations for date picker |
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();
}
}