Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(grid): expose editorOptions for the default editors and improve built-in editing for date/time cols (input formats) #14465

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
77a8696
feat(date-time-util): logic to identify numeric formats for editing
ddaribo Jul 3, 2024
705de49
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Jul 3, 2024
334cba2
chore(date-time-util): formatting fixes
ddaribo Jul 3, 2024
3648659
Merge branch 'bpachilova/grid-editor-options-feat-14009' of https://g…
ddaribo Jul 3, 2024
e24c974
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Jul 12, 2024
82c1fd3
fix(esf-styles): small margin fix for time picker
ddaribo Jul 12, 2024
602d25d
feat(grid-interface): add editorOptions property on the ColumnType an…
ddaribo Jul 12, 2024
282c896
feat(grid-column): get/set editorOptions and dateTimeFormat
ddaribo Jul 12, 2024
ca0f4f5
feat(grid-cells): use editorOptions.dateTimeFormat; add locale where …
ddaribo Jul 12, 2024
78e76c1
feat(grid-filters): use editorOptions.dateTimeFormat and locale on fi…
ddaribo Jul 12, 2024
6c8e88e
test(grid-column-and-filtering): editors input formats
ddaribo Jul 12, 2024
913a7cd
chore(grid-cells): delete leftover inputFormat bindings
ddaribo Jul 12, 2024
fb063af
chore(column-test): fix time col format test check
ddaribo Jul 12, 2024
d5264e1
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Jul 15, 2024
dcd9517
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Jul 15, 2024
017fdfb
feat(date-time-util): default locale-based format for time and date-t…
ddaribo Jul 17, 2024
4c0b4fa
feat(date-time-editors): handle default inputFormat based on locale
ddaribo Jul 17, 2024
cac8366
feat(date-time-util): localize predefined formats used for input; ref…
ddaribo Jul 19, 2024
6cee547
feat(date-range): handle inputFormat when locale is changed
ddaribo Jul 19, 2024
360bc67
feat(dte-dir,pickers): handle locale change and display/input formats
ddaribo Jul 19, 2024
26708b2
refactor(column): do not handle format transformations here
ddaribo Jul 19, 2024
8e1196b
refactor(qb): editorOptions.defaultDateTimeFormat setting
ddaribo Jul 19, 2024
b06fe16
refactor(filtering-ui-test): adjust according to latest changes
ddaribo Jul 19, 2024
02cbe4c
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Jul 19, 2024
b08258c
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ChronosSF Aug 5, 2024
c9b5331
refactor(column): address comment - simplify editorOptions assignment
ddaribo Aug 9, 2024
45ddab0
chore(column): remove unused import
ddaribo Aug 9, 2024
8ce97fa
chore(docs): update changelog, grid feature readme
ddaribo Aug 13, 2024
a65d264
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Aug 15, 2024
14a6984
chore(*): fixing lint error
ddaribo Aug 15, 2024
188e1ac
chore(docs): move changelog entry under 18.2.0
ddaribo Aug 21, 2024
90018ee
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Aug 21, 2024
d90f85f
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ddaribo Sep 2, 2024
98cac6b
Merge branch 'master' into bpachilova/grid-editor-options-feat-14009
ChronosSF Sep 12, 2024
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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ For Firefox users, we provide limited scrollbar styling options through the foll
- `--sb-thumb-bg-color`: Sets the background color of the scrollbar thumb.
- `--sb-track-bg-color`: Sets the background color of the scrollbar track.

#### Column editor options
- `ColumnType`, `IgxColumn`
- Added a new `editorOptions` property that allows to pass optional parameters to control properties of the default column editors. Accepts an `IColumnEditorOptions` object with the `dateTimeFormat` property, that would be used as input format for the editors of
`date`, `dateTime` and `time` column data types:
```ts
const editorOptions: IColumnEditorOptions = {
dateTimeFormat: 'MM/dd/YYYY',
}
```
```html
<igx-column field="sampleDate" dataType="date" [editorOptions]="editorOptions"></igx-column>
```
If not set, the `dateTimeFormat` resolves to the `pipeArgs.displayFormat` property of the column, in case it is set and contains only numeric date-time parts or such that can be handled by the editors. Alternatively, a fallback input format as per the `IgxGrid`'s `locale` is used.

### General
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`, `IgxPivotGrid`
- **Breaking Change** The `shouldGenerate` property have been deprecated and will be removed in a future version. Use `autoGenerate` instead. Automatic migration to this is available and will be applied on `ng update`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,8 @@
margin: rem(16px) 0;

~ igx-input-group,
~ igx-date-picker {
~ igx-date-picker,
~ igx-time-picker {
margin-inline-start: rem(16px);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { IGX_INPUT_GROUP_TYPE, IgxInputGroupType } from '../input-group/inputGro
import { IgxPrefixDirective } from '../directives/prefix/prefix.directive';
import { IgxSuffixDirective } from '../directives/suffix/suffix.directive';
import { IgxInputGroupComponent } from '../input-group/input-group.component';
import { DateTimeUtil } from './util/date-time.util';
import { DataType } from '../data-operations/data-util';

@Directive()
export abstract class PickerBaseDirective implements IToggleView, EditorProvider, AfterViewInit, AfterContentChecked, OnDestroy {
Expand All @@ -29,15 +31,23 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
*
* @remarks
* Also used as a placeholder when none is provided.
* Default is `"'MM/dd/yyyy'"`
*
* @example
* ```html
* <igx-date-picker inputFormat="dd/MM/yy"></igx-date-picker>
* ```
*/
@Input()
public inputFormat: string;
public set inputFormat(value: string) {
if (value) {
this._userSetFormat = value;
this._inputFormat = DateTimeUtil.getNumericInputFormat(this.locale, value);
}
}

public get inputFormat(): string {
return this._inputFormat || this._defaultInputFormat;
}

/**
* The format used to display the picker's value when it's not being edited.
Expand Down Expand Up @@ -128,6 +138,9 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
} catch (e) {
this._locale = this._localeId;
}
// reassign the inputFormat in case the original one needs to be localized
this.inputFormat = this._userSetFormat;
this.updateDefaultFormat();
}

/**
Expand Down Expand Up @@ -251,9 +264,12 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider

protected _locale: string;
protected _collapsed = true;
protected _defaultInputFormat: string;
protected _inputFormat: string;
protected _type: IgxInputGroupType;
protected _minValue: Date | string;
protected _maxValue: Date | string;
protected _userSetFormat: string;
protected _weekStart: WEEKDAYS | number;

/**
Expand Down Expand Up @@ -318,6 +334,10 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
});
}

protected updateDefaultFormat(): void {
this._defaultInputFormat = DateTimeUtil.getDefaultInputFormat(this.locale, DataType.Date);
}

public abstract select(value: Date | DateRange | string): void;
public abstract open(settings?: OverlaySettings): void;
public abstract toggle(settings?: OverlaySettings): void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { DateTimeUtil } from './date-time.util';
import { DatePart, DatePartInfo } from '../../directives/date-time-editor/date-time-editor.common';
import { registerLocaleData } from '@angular/common';
import localeBg from '@angular/common/locales/bg';
import { DataType } from '../../data-operations/data-util';

const reduceToDictionary = (parts: DatePartInfo[]) => parts.reduce((obj, x) => {
obj[x.type] = x;
Expand Down Expand Up @@ -233,6 +236,30 @@ describe(`DateTimeUtil Unit tests`, () => {
expect(result).toEqual('MM/dd/yyyy');
});

it('should properly build input formats based on locale for dateTime data type ', () => {
spyOn(DateTimeUtil, 'getDefaultInputFormat').and.callThrough();
let result = DateTimeUtil.getDefaultInputFormat('en-US', DataType.DateTime);
expect(result).toEqual('MM/dd/yyyy, hh:mm:ss tt');

result = DateTimeUtil.getDefaultInputFormat('bg-BG', DataType.DateTime);
expect(result.normalize('NFKC')).toEqual('dd.MM.yyyy г., HH:mm:ss');

result = DateTimeUtil.getDefaultInputFormat('fr-FR', DataType.DateTime);
expect(result).toEqual('dd/MM/yyyy HH:mm:ss');
});

it('should properly build input formats based on locale for time data type ', () => {
spyOn(DateTimeUtil, 'getDefaultInputFormat').and.callThrough();
let result = DateTimeUtil.getDefaultInputFormat('en-US', DataType.Time);
expect(result).toEqual('hh:mm tt');

result = DateTimeUtil.getDefaultInputFormat('bg-BG', DataType.Time);
expect(result.normalize('NFKC')).toEqual('HH:mm');

result = DateTimeUtil.getDefaultInputFormat('fr-FR', DataType.Time);
expect(result).toEqual('HH:mm');
});

it('should correctly distinguish date from time characters', () => {
expect(DateTimeUtil.isDateOrTimeChar('d')).toBeTrue();
expect(DateTimeUtil.isDateOrTimeChar('M')).toBeTrue();
Expand Down Expand Up @@ -628,4 +655,60 @@ describe(`DateTimeUtil Unit tests`, () => {
expect(DateTimeUtil.isValidDate(false)).toBeFalse();
expect(DateTimeUtil.isValidDate(true)).toBeFalse();
});

it('should correctly identify formats that would resolve to only numeric parts (and period) for the date/time parts', () => {
// test with locale covering non-ASCII characters as well
registerLocaleData(localeBg, 'bg');
const locale = 'bg';

const numericFormats = ['y', 'yy', 'yyy', 'yyyy', 'M', 'MM', 'd', 'dd', 'h', 'hh',
'H', 'HH', 'm', 'mm', 's', 'ss', 'S', 'SS', 'SSS',
'dd-MM-yyyy', 'dd/M/yyyy HH:mm:ss tt', 'dd/M/yyyy HH:mm:ss:SS a',
// literals are allowed in the format
'dd/MM/yyyy test hh:mm'
];
numericFormats.forEach(format => {
expect(DateTimeUtil.isFormatNumeric(locale, format)).withContext(`Format: ${format}`).toBeTrue();
});

const nonNumericFormats = ['MMM', 'MMMM', 'MMMMM', 'medium', 'long', 'full', 'mediumDate',
'longDate', 'fullDate', 'longTime', 'fullTime', 'dd-MMM-yyyy', 'E', 'EE'];

nonNumericFormats.forEach(format => {
expect(DateTimeUtil.isFormatNumeric(locale, format)).withContext(`Format: ${format}`).toBeFalse();
});
});

it('getNumericInputFormat should return formats with date parts that the date-time editors can handle', () => {
let locale = 'en-US';

// returns the equivalent of the predefined numeric formats as date parts
// should be transformed as inputFormats for editing (numeric year, 2-digit parts for the rest)
expect(DateTimeUtil.getNumericInputFormat(locale, 'short')).toBe('MM/dd/yyyy, hh:mm tt');
expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate')).toBe('MM/dd/yyyy');
expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime').normalize('NFKD')).toBe('hh:mm tt');
expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime').normalize('NFKD')).toBe('hh:mm:ss tt');

// handle the predefined formats for different locales
locale = 'bg-BG';
expect(DateTimeUtil.getNumericInputFormat(locale, 'short').normalize('NFKD')).toBe('dd.MM.yyyy г., HH:mm');
expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate').normalize('NFKD')).toBe('dd.MM.yyyy г.');
expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime').normalize('NFKD')).toBe('HH:mm');
expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime').normalize('NFKD')).toBe('HH:mm:ss');

locale = 'ja-JP';
expect(DateTimeUtil.getNumericInputFormat(locale, 'short')).toBe('yyyy/MM/dd HH:mm');
expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate')).toBe('yyyy/MM/dd');
expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime').normalize('NFKD')).toBe('HH:mm');
expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime').normalize('NFKD')).toBe('HH:mm:ss');

// returns the same format if it is custom and numeric
expect(DateTimeUtil.getNumericInputFormat(locale, 'dd-MM-yyyy')).toBe('dd-MM-yyyy');
expect(DateTimeUtil.getNumericInputFormat(locale, 'dd/M/yyyy hh:mm:ss:SS aa')).toBe('dd/M/yyyy hh:mm:ss:SS aa');

// returns empty string if predefined and not among the numeric ones
expect(DateTimeUtil.getNumericInputFormat(locale, 'medium')).toBe('');
expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumDate')).toBe('');
expect(DateTimeUtil.getNumericInputFormat(locale, 'longTime')).toBe('');
});
});
Loading
Loading