Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/app/examples/grid-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,9 @@ export class GridEditorComponent implements OnInit {
filter: { model: Filters.compoundDate },
formatter: Formatters.dateIso,
exportWithFormatter: true,
type: FieldType.date,
type: FieldType.date, // dataset cell input format
// outputType: FieldType.dateUs, // date picker format
saveOutputType: FieldType.dateUtc, // save output date formattype: FieldType.date,
editor: {
model: Editors.date,
// override any of the Flatpickr options through "editorOptions"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,36 +210,64 @@ describe('DateEditor', () => {

expect(editor.isValueChanged()).toBe(false);
});

it('should return False when input date is invalid', () => {
mockItemData = { id: 1, startDate: '1900-02-32', isActive: true };
mockColumn.type = FieldType.dateUs;
mockColumn.internalColumnEditor.editorOptions = { allowInput: true }; // change to allow input value only for testing purposes

editor = new DateEditor(editorArguments);
editor.loadValue(mockItemData);
const editorInputElm = divContainer.querySelector<HTMLInputElement>('input.flatpickr-alt-input');
editorInputElm.value = '1900-02-32';
editorInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keydown', { keyCode: 13, bubbles: true, cancelable: true }));

expect(editor.isValueChanged()).toBe(false);
});
});

describe('applyValue method', () => {
it('should apply the value to the startDate property when it passes validation', () => {
it('should apply the value to the startDate property with ISO format when no "outputType" is defined and when it passes validation', () => {
mockColumn.internalColumnEditor.validator = null;
mockColumn.type = FieldType.dateTimeIsoAmPm;
mockColumn.type = FieldType.date;
mockItemData = { id: 1, startDate: '2001-04-05T11:33:42.000Z', isActive: true };

const newDate = '2001-01-02T16:02:02.000+05:00';
const newDate = new Date(Date.UTC(2001, 0, 2, 16, 2, 2, 0));
editor = new DateEditor(editorArguments);
editor.applyValue(mockItemData, newDate);

expect(mockItemData).toEqual({ id: 1, startDate: moment(newDate, 'YYYY-MM-DD hh:mm:ss a').toDate(), isActive: true });
expect(mockItemData).toEqual({ id: 1, startDate: moment(newDate).format('YYYY-MM-DD'), isActive: true });
});

it('should apply the value to the startDate property with a field having dot notation (complex object) that passes validation', () => {
it('should apply the value to the startDate property with "outputType" format with a field having dot notation (complex object) that passes validation', () => {
mockColumn.internalColumnEditor.validator = null;
mockColumn.type = FieldType.dateTimeIsoAmPm;
mockColumn.type = FieldType.date;
mockColumn.outputType = FieldType.dateTimeIsoAmPm;
mockColumn.field = 'employee.startDate';
mockItemData = { id: 1, employee: { startDate: new Date(Date.UTC(2001, 3, 5, 16, 11, 33, 0)) }, isActive: true };
mockItemData = { id: 1, employee: { startDate: '2001-04-05T11:33:42.000Z' }, isActive: true };

const newDate = new Date(Date.UTC(2001, 0, 2, 16, 2, 2, 0));
editor = new DateEditor(editorArguments);
editor.applyValue(mockItemData, newDate);

expect(mockItemData).toEqual({ id: 1, employee: { startDate: moment(newDate).format('YYYY-MM-DD hh:mm:ss a') }, isActive: true });
});

it('should apply the value to the startDate property with output format defined by "saveOutputType" when it passes validation', () => {
mockColumn.internalColumnEditor.validator = null;
mockColumn.type = FieldType.date;
mockColumn.saveOutputType = FieldType.dateTimeIsoAmPm;
mockItemData = { id: 1, startDate: '2001-04-05T11:33:42.000Z', isActive: true };

const newDate = '2001-01-02T16:02:02.000+05:00';
const newDate = new Date(Date.UTC(2001, 0, 2, 16, 2, 2, 0));
editor = new DateEditor(editorArguments);
editor.applyValue(mockItemData, newDate);

expect(mockItemData).toEqual({ id: 1, employee: { startDate: moment(newDate, 'YYYY-MM-DD hh:mm:ss a').toDate() }, isActive: true });
expect(mockItemData).toEqual({ id: 1, startDate: moment(newDate).format('YYYY-MM-DD hh:mm:ss a'), isActive: true });
});

it('should return item data with an empty string in its value when it fails the custom validation', () => {
mockColumn.internalColumnEditor.validator = (value: any, args: EditorArgs) => {
mockColumn.internalColumnEditor.validator = (value: any) => {
if (value.length > 10) {
return { valid: false, msg: 'Must be at least 10 chars long.' };
}
Expand Down
45 changes: 26 additions & 19 deletions src/app/modules/angular-slickgrid/editors/dateEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export class DateEditor implements Editor {
const placeholder = this.columnEditor && this.columnEditor.placeholder || '';
const title = this.columnEditor && this.columnEditor.title || '';
this.defaultDate = (this.args.item) ? this.args.item[this.columnDef.field] : null;
const inputFormat = mapFlatpickrDateFormatWithFieldType(this.columnDef.type || FieldType.dateUtc);
const outputFormat = mapFlatpickrDateFormatWithFieldType(this.columnDef.outputType || this.columnDef.type || FieldType.dateUtc);
let currentLocale = this._translate && this._translate.currentLang || this.gridOptions.locale || 'en';
if (currentLocale && currentLocale.length > 2) {
Expand All @@ -106,12 +107,10 @@ export class DateEditor implements Editor {
defaultDate: this.defaultDate as string,
altInput: true,
altFormat: outputFormat,
dateFormat: outputFormat,
dateFormat: inputFormat,
closeOnSelect: false,
locale: (currentLocale !== 'en') ? this.loadFlatpickrLocale(currentLocale) : 'en',
onChange: (selectedDates: Date[] | Date, dateStr: string, instance: any) => {
this.save();
},
onChange: () => this.save(),
errorHandler: () => {
// do nothing, Flatpickr is a little too sensitive and will throw an error when provided date is lower than minDate so just disregard the error completely
}
Expand Down Expand Up @@ -174,26 +173,33 @@ export class DateEditor implements Editor {

applyValue(item: any, state: any) {
const fieldName = this.columnDef && this.columnDef.field;
const outputTypeFormat = mapMomentDateFormatWithFieldType((this.columnDef && (this.columnDef.outputType || this.columnDef.type)) || FieldType.dateUtc);
const isComplexObject = fieldName.indexOf('.') > 0; // is the field a complex object, "address.streetNumber"

// validate the value before applying it (if not valid we'll set an empty string)
const validation = this.validate(state);
const newValue = (validation && validation.valid) ? moment(state, outputTypeFormat).toDate() : '';

// set the new value to the item datacontext
if (isComplexObject) {
setDeepValue(item, fieldName, newValue);
} else {
item[fieldName] = newValue;
if (fieldName !== undefined) {
const outputTypeFormat = mapMomentDateFormatWithFieldType((this.columnDef && (this.columnDef.outputType || this.columnDef.type)) || FieldType.dateUtc);
const saveTypeFormat = mapMomentDateFormatWithFieldType((this.columnDef && (this.columnDef.saveOutputType || this.columnDef.outputType || this.columnDef.type)) || FieldType.dateUtc);
const isComplexObject = fieldName.indexOf('.') > 0; // is the field a complex object, "address.streetNumber"

// validate the value before applying it (if not valid we'll set an empty string)
const validation = this.validate(state);
const newValue = (validation && validation.valid) ? moment(state, outputTypeFormat).format(saveTypeFormat) : '';

// set the new value to the item datacontext
if (isComplexObject) {
setDeepValue(item, fieldName, newValue);
} else {
item[fieldName] = newValue;
}
}
}

isValueChanged() {
const elmValue = this._$input.val();
const inputFormat = mapMomentDateFormatWithFieldType(this.columnDef && this.columnDef.type || FieldType.dateIso);
const outputTypeFormat = mapMomentDateFormatWithFieldType((this.columnDef && (this.columnDef.outputType || this.columnDef.type)) || FieldType.dateUtc);
const elmDateStr = elmValue ? moment(elmValue, outputTypeFormat, false).format(outputTypeFormat) : '';
const orgDateStr = this.originalDate ? moment(this.originalDate, outputTypeFormat, false).format(outputTypeFormat) : '';
const elmDateStr = elmValue ? moment(elmValue, inputFormat, false).format(outputTypeFormat) : '';
const orgDateStr = this.originalDate ? moment(this.originalDate, inputFormat, false).format(outputTypeFormat) : '';
if (elmDateStr === 'Invalid date' || orgDateStr === 'Invalid date') {
return false;
}

return (!(elmDateStr === '' && orgDateStr === '')) && (elmDateStr !== orgDateStr);
}
Expand Down Expand Up @@ -232,8 +238,9 @@ export class DateEditor implements Editor {
return '';
}

const inputFormat = mapMomentDateFormatWithFieldType(this.columnDef && this.columnDef.type || FieldType.dateIso);
const outputTypeFormat = mapMomentDateFormatWithFieldType((this.columnDef && (this.columnDef.outputType || this.columnDef.type)) || FieldType.dateIso);
const value = moment(domValue, outputTypeFormat, false).format(outputTypeFormat);
const value = moment(domValue, inputFormat, false).format(outputTypeFormat);

return value;
}
Expand Down
11 changes: 10 additions & 1 deletion src/app/modules/angular-slickgrid/models/column.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,18 @@ export interface Column<T = any> {
/** an event that can be used for triggering an action after a cell click */
onCellClick?: (e: KeyboardEvent | MouseEvent, args: OnEventArgs) => void;

/** column output type */
/**
* Column output type(e.g.Date Picker, the output format that we will see in the picker)
* NOTE: this is only currently used by the Editors / Filters with a Date Picker
*/
outputType?: FieldType;

/**
* Column Editor save format type (e.g. which date format to use when saving after choosing a date from the Date Editor picker)
* NOTE: this is only currently used by the Date Editor (date picker)
*/
saveOutputType?: FieldType;

/** if you want to pass custom paramaters to your Formatter/Editor or anything else */
params?: any | any[];

Expand Down