Skip to content

Commit

Permalink
Datepicker update
Browse files Browse the repository at this point in the history
  • Loading branch information
klaascuvelier committed Apr 10, 2024
1 parent 27e4e6c commit 07d0a5f
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 145 deletions.
149 changes: 69 additions & 80 deletions src/datepicker-input/datepicker-input.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,101 +5,92 @@ import {
EventEmitter,
ElementRef,
TemplateRef,
ViewChild
ViewChild, HostBinding
} from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";

@Component({
selector: "cds-date-picker-input, ibm-date-picker-input",
template: `
<div class="cds--form-item">
<div class="cds--date-picker"
<label
*ngIf="label"
[for]="id"
class="cds--label"
[ngClass]="{'cds--label--disabled': disabled}">
<ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container>
<ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template>
</label>
<div class="cds--date-picker-input__wrapper"
[ngClass]="{
'cds--date-picker--simple' : type === 'simple',
'cds--date-picker--single' : type === 'single',
'cds--date-picker--range' : type === 'range',
'cds--date-picker--light' : theme === 'light',
'cds--skeleton' : skeleton
'cds--date-picker-input__wrapper--invalid': invalid,
'cds--date-picker-input__wrapper--warn': warn
}">
<div class="cds--date-picker-container">
<label
*ngIf="label"
[for]="id"
class="cds--label"
[ngClass]="{'cds--label--disabled': disabled}">
<ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container>
<ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template>
</label>
<div class="cds--date-picker-input__wrapper"
<span>
<input
#input
*ngIf="!skeleton"
autocomplete="off"
type="text"
class="cds--date-picker__input"
[ngClass]="{
'cds--date-picker-input__wrapper--invalid': invalid,
'cds--date-picker-input__wrapper--warn': warn
}">
<span>
<input
#input
*ngIf="!skeleton"
autocomplete="off"
type="text"
class="cds--date-picker__input"
[ngClass]="{
'cds--date-picker__input--sm': size === 'sm',
'cds--date-picker__input--md': size === 'md',
'cds--date-picker__input--lg': size === 'lg'
}"
[attr.data-invalid]="invalid ? true : undefined"
[value]="value"
[pattern]="pattern"
[placeholder]="placeholder"
[id]= "id"
[disabled]="disabled"
(change)="onChange($event)"/>
<svg
*ngIf="type !== 'simple' && !warn && !invalid"
cdsIcon="calendar"
size="16"
class="cds--date-picker__icon">
</svg>
<svg
*ngIf="invalid"
class="cds--date-picker__icon cds--date-picker__icon--invalid"
cdsIcon="warning--filled"
size="16">
</svg>
<svg
*ngIf="!invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--date-picker__icon cds--date-picker__icon--warn">
</svg>
</span>
</div>
<div
*ngIf="helperText && !invalid && !warn"
class="cds--form__helper-text"
[ngClass]="{'cds--form__helper-text--disabled': disabled}">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template>
</div>
<div *ngIf="invalid" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template>
</div>
<div *ngIf="!invalid && warn" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template>
</div>
</div>
'cds--date-picker__input--sm': size === 'sm',
'cds--date-picker__input--md': size === 'md',
'cds--date-picker__input--lg': size === 'lg'
}"
[attr.data-invalid]="invalid ? true : undefined"
[value]="value"
[pattern]="pattern"
[placeholder]="placeholder"
[id]= "id"
[disabled]="disabled"
(change)="onChange($event)"
/>
<svg
*ngIf="type !== 'simple' && !warn && !invalid"
cdsIcon="calendar"
size="16"
class="cds--date-picker__icon">
</svg>
<svg
*ngIf="invalid"
class="cds--date-picker__icon cds--date-picker__icon--invalid"
cdsIcon="warning--filled"
size="16">
</svg>
<svg
*ngIf="!invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--date-picker__icon cds--date-picker__icon--warn">
</svg>
</span>
</div>
<div
*ngIf="helperText && !invalid && !warn"
class="cds--form__helper-text"
[ngClass]="{'cds--form__helper-text--disabled': disabled}">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template>
</div>
<div *ngIf="invalid" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template>
</div>
<div *ngIf="!invalid && warn" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template>
</div>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DatePickerInput,
multi: true
}
]
],
host: {
"class": 'cds--date-picker-container'
}
})
export class DatePickerInput {
private static datePickerCount = 0;
Expand All @@ -111,8 +102,6 @@ export class DatePickerInput {

@Input() id = `datepicker-${DatePickerInput.datePickerCount++}`;

@Input() hasIcon = false;

@Input() label: string | TemplateRef<any>;

@Input() placeholder = "mm/dd/yyyy";
Expand Down
111 changes: 52 additions & 59 deletions src/datepicker/datepicker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,54 +58,50 @@ if (languages.default?.default["en"]?.weekdays) {
<div
class="cds--date-picker"
[ngClass]="{
'cds--date-picker--range' : range,
'cds--date-picker--single' : !range,
'cds--date-picker--simple' : datePickerType === 'simple',
'cds--date-picker--range' : datePickerType === 'range',
'cds--date-picker--single' : datePickerType === 'single',
'cds--date-picker--light' : theme === 'light',
'cds--skeleton' : skeleton
}">
<div class="cds--date-picker-container">
<cds-date-picker-input
#input
[label]="label"
[placeholder]="placeholder"
[pattern]="inputPattern"
[id]="id + '-input'"
[size]="size"
[type]="(range ? 'range' : 'single')"
[hasIcon]="(range ? false : true)"
[disabled]="disabled"
[invalid]="invalid"
[invalidText]="invalidText"
[warn]="warn"
[warnText]="warnText"
[skeleton]="skeleton"
[helperText]="helperText"
(valueChange)="onValueChange($event)"
(click)="openCalendar(input)">
</cds-date-picker-input>
</div>
<div *ngIf="range" class="cds--date-picker-container">
<cds-date-picker-input
#rangeInput
[label]="rangeLabel"
[placeholder]="placeholder"
[pattern]="inputPattern"
[id]="id + '-rangeInput'"
[size]="size"
[type]="(range ? 'range' : 'single')"
[hasIcon]="(range ? true : null)"
[disabled]="disabled"
[invalid]="rangeInvalid"
[invalidText]="rangeInvalidText"
[warn]="rangeWarn"
[warnText]="rangeWarnText"
[skeleton]="skeleton"
[helperText]="rangeHelperText"
(valueChange)="onRangeValueChange($event)"
(click)="openCalendar(rangeInput)">
</cds-date-picker-input>
</div>
<cds-date-picker-input
#input
[label]="label"
[placeholder]="placeholder"
[pattern]="inputPattern"
[id]="id + '-input'"
[size]="size"
[type]="datePickerType"
[disabled]="disabled"
[invalid]="invalid"
[invalidText]="invalidText"
[warn]="warn"
[warnText]="warnText"
[skeleton]="skeleton"
[helperText]="helperText"
(valueChange)="onValueChange($event)"
(click)="openCalendar(input)">
</cds-date-picker-input>
<cds-date-picker-input
*ngIf="datePickerType === 'range'"
#rangeInput
[label]="rangeLabel"
[placeholder]="placeholder"
[pattern]="inputPattern"
[id]="id + '-rangeInput'"
[size]="size"
type="range"
[disabled]="disabled"
[invalid]="rangeInvalid"
[invalidText]="rangeInvalidText"
[warn]="rangeWarn"
[warnText]="rangeWarnText"
[skeleton]="skeleton"
[helperText]="rangeHelperText"
(valueChange)="onRangeValueChange($event)"
(click)="openCalendar(rangeInput)">
</cds-date-picker-input>
</div>
</div>
`,
Expand All @@ -126,10 +122,7 @@ export class DatePicker implements
AfterViewInit {
private static datePickerCount = 0;

/**
* Select calendar range mode
*/
@Input() range = false;
@Input() datePickerType: "simple" | "single" | "range" = "simple";

/**
* Format of date
Expand Down Expand Up @@ -228,11 +221,11 @@ export class DatePicker implements
}
get flatpickrOptions(): Partial<Options> {
const plugins = [...this.plugins, carbonFlatpickrMonthSelectPlugin];
if (this.range) {
if (this.datePickerType === "range") {
plugins.push(rangePlugin({ input: `#${this.id}-rangeInput`, position: "left" }));
}
return Object.assign({}, this._flatpickrOptions, this.flatpickrBaseOptions, {
mode: this.range ? "range" : "single",
mode: this.datePickerType === "range" ? "range" : "single",
plugins,
dateFormat: this.dateFormat,
locale: languages.default?.default[this.language] || languages.default[this.language]
Expand Down Expand Up @@ -268,7 +261,7 @@ export class DatePicker implements
onClose: (date) => {
// This makes sure that the `flatpickrInstance selectedDates` are in sync with the values of
// the inputs when the calendar closes.
if (this.range && this.flatpickrInstance) {
if (this.datePickerType === "range" && this.flatpickrInstance) {
const inputValue = this.input.input.nativeElement.value;
const rangeInputValue = this.rangeInput.input.nativeElement.value;
if (inputValue || rangeInputValue) {
Expand Down Expand Up @@ -332,7 +325,7 @@ export class DatePicker implements
// and because we rely on a library that operates outside the Angular view of the world
// we need to keep trying to load the library, until the relevant DOM is actually live
ngAfterViewChecked() {
if (!this.isFlatpickrLoaded()) {
if (this.datePickerType !== "simple" && !this.isFlatpickrLoaded()) {
// @ts-ignore ts is unhappy with the below call to `flatpickr`
this.flatpickrInstance = flatpickr(`#${this.id}-input`, this.flatpickrOptions);
// if (and only if) the initialization succeeded, we can set the date values
Expand All @@ -348,7 +341,7 @@ export class DatePicker implements
onFocus() {
// Updates the month manually when calendar mode is range because month
// will not update properly without manually updating them on focus.
if (this.range) {
if (this.datePickerType === "range") {
if (this.rangeInput.input.nativeElement === document.activeElement && this.flatpickrInstance.selectedDates[1]) {
const currentMonth = this.flatpickrInstance.selectedDates[1].getMonth();
this.flatpickrInstance.changeMonth(currentMonth, false);
Expand Down Expand Up @@ -414,7 +407,7 @@ export class DatePicker implements
onValueChange(event: string) {
if (this.isFlatpickrLoaded()) {
const date = this.flatpickrInstance.parseDate(event, this.dateFormat);
if (this.range) {
if (this.datePickerType === "range") {
this.setDateValues([date, this.flatpickrInstance.selectedDates[1]]);
} else {
this.setDateValues([date]);
Expand All @@ -438,7 +431,7 @@ export class DatePicker implements
* Handles opening the calendar "properly" when the calendar icon is clicked.
*/
openCalendar(datepickerInput: DatePickerInput) {
if (this.range) {
if (this.datePickerType === "range") {
datepickerInput.input.nativeElement.click();

// If the first input's calendar icon is clicked when calendar is in range mode, then
Expand Down Expand Up @@ -469,7 +462,7 @@ export class DatePicker implements
* Handles the initialization of event listeners for the datepicker input and range input fields.
*/
protected addInputListeners() {
if (!this.isFlatpickrLoaded()) {
if (this.datePickerType === "simple" || !this.isFlatpickrLoaded()) {
return;
}

Expand Down Expand Up @@ -520,7 +513,7 @@ export class DatePicker implements
* @param newDates An optional SimpleChange of date values
*/
protected resetFlatpickrInstance(newDates?: SimpleChange) {
if (this.isFlatpickrLoaded()) {
if (this.datePickerType !== "simple" && this.isFlatpickrLoaded()) {
let dates = this.flatpickrInstance.selectedDates;
if (newDates && this.didDateValueChange(newDates.currentValue, newDates.previousValue)) {
dates = newDates.currentValue;
Expand Down Expand Up @@ -646,7 +639,7 @@ export class DatePicker implements
// In range mode, if a date is selected from the first calendar that is from the previous month,
// the month will not be updated on the calendar until the calendar is re-opened.
// This will make sure the calendar is updated with the correct month.
if (this.range && this.flatpickrInstance.selectedDates[0]) {
if (this.datePickerType === "range" && this.flatpickrInstance.selectedDates[0]) {
const currentMonth = this.flatpickrInstance.selectedDates[0].getMonth();

// `flatpickrInstance.changeMonth` removes the focus on the selected date element and will
Expand Down
Loading

0 comments on commit 07d0a5f

Please sign in to comment.