Skip to content

Commit 778985c

Browse files
refactor(date-time-editor): can set placeholder with inputFormat applied
- clean up masking logic
1 parent 5d106fc commit 778985c

File tree

2 files changed

+77
-38
lines changed

2 files changed

+77
-38
lines changed

projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.spec.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ describe('IgxDateTimeEditor', () => {
3737
dateTimeEditor.ngOnChanges(changes);
3838
};
3939
describe('Properties & Events', () => {
40-
it('should emit valueChange event on clear()', () => {
40+
it('should emit valueChange event on clear()', () => {
4141
inputFormat = 'dd/M/yy';
4242
inputDate = '6/6/2000';
43-
elementRef = { nativeElement: { value: inputDate, setSelectionRange: () => {} } };
43+
elementRef = { nativeElement: { value: inputDate, setSelectionRange: () => { } } };
4444
initializeDateTimeEditor();
4545

4646
const date = new Date(2000, 5, 6);
@@ -61,13 +61,13 @@ describe('IgxDateTimeEditor', () => {
6161
initializeDateTimeEditor();
6262

6363
dateTimeEditor.inputFormat = inputFormat;
64-
expect(dateTimeEditor.mask).toEqual('0/0/00');
64+
expect(dateTimeEditor.mask).toEqual('00/00/00');
6565

6666
dateTimeEditor.inputFormat = 'dd-MM-yyyy HH:mm:ss';
6767
expect(dateTimeEditor.mask).toEqual('00-00-0000 00:00:00');
6868

6969
dateTimeEditor.inputFormat = 'H:m:s';
70-
expect(dateTimeEditor.mask).toEqual('0:0:0');
70+
expect(dateTimeEditor.mask).toEqual('00:00:00');
7171
});
7272
});
7373

@@ -977,6 +977,30 @@ describe('IgxDateTimeEditor', () => {
977977
fixture.detectChanges();
978978
expect(dateTimeEditorDirective.value.getDate()).toEqual(today.getDate() - 1);
979979
}));
980+
981+
it('should properly set placeholder with inputFormat applied', () => {
982+
fixture.componentInstance.placeholder = 'Date:';
983+
fixture.detectChanges();
984+
expect(dateTimeEditorDirective.nativeElement.placeholder).toEqual('Date:');
985+
});
986+
987+
it('should be able to switch placeholders at runtime', () => {
988+
let placeholder = 'Placeholder';
989+
fixture.componentInstance.placeholder = placeholder;
990+
fixture.detectChanges();
991+
expect(dateTimeEditorDirective.nativeElement.placeholder).toEqual(placeholder);
992+
993+
placeholder = 'Placeholder1';
994+
fixture.componentInstance.placeholder = placeholder;
995+
fixture.detectChanges();
996+
expect(dateTimeEditorDirective.nativeElement.placeholder).toEqual(placeholder);
997+
998+
// when an empty placeholder (incl. null, undefined) is provided, at run-time, we do not default to the inputFormat
999+
placeholder = '';
1000+
fixture.componentInstance.placeholder = placeholder;
1001+
fixture.detectChanges();
1002+
expect(dateTimeEditorDirective.nativeElement.placeholder).toEqual(placeholder);
1003+
});
9801004
});
9811005

9821006
describe('Form control tests: ', () => {
@@ -1065,6 +1089,12 @@ describe('IgxDateTimeEditor', () => {
10651089
fixture.componentInstance.submit();
10661090
expect(result).toBe(inputDate);
10671091
});
1092+
1093+
it('should default to inputFormat as placeholder if none is provided', () => {
1094+
fixture.componentInstance.dateTimeFormat = 'dd/MM/yyyy';
1095+
fixture.detectChanges();
1096+
expect(dateTimeEditorDirective.nativeElement.placeholder).toEqual('dd/MM/yyyy');
1097+
});
10681098
});
10691099
});
10701100
});
@@ -1074,9 +1104,11 @@ describe('IgxDateTimeEditor', () => {
10741104
template: `
10751105
<igx-input-group #igxInputGroup>
10761106
<input type="text" igxInput [disabled]="disabled" [readonly]="readonly"
1077-
[igxDateTimeEditor]="dateTimeFormat" [displayFormat]="displayFormat"
1107+
[igxDateTimeEditor]="dateTimeFormat" [displayFormat]="displayFormat" [placeholder]="placeholder"
10781108
[(ngModel)]="date" [minValue]="minDate" [maxValue]="maxDate" [promptChar]="promptChar"/>
10791109
</igx-input-group>
1110+
1111+
<input [(ngModel)]="placeholder" />
10801112
`
10811113
})
10821114
export class IgxDateTimeEditorSampleComponent {
@@ -1089,11 +1121,12 @@ export class IgxDateTimeEditorSampleComponent {
10891121
public promptChar = '_';
10901122
public disabled = false;
10911123
public readonly = false;
1124+
public placeholder = null;
10921125
}
10931126

10941127
@Component({
10951128
template: `
1096-
<form (ngSubmit)="submit()" [formGroup]="reactiveForm">
1129+
<form (ngSubmit)="submit()" [formGroup]="reactiveForm">
10971130
<igx-input-group>
10981131
<input formControlName="dateEditor" type="text"
10991132
igxInput [igxDateTimeEditor]="dateTimeFormat" [minValue]="minDate" [maxValue]="maxDate"/>

projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import {
33
Directive, Input, ElementRef,
44
Renderer2, NgModule, Output, EventEmitter, Inject,
5-
LOCALE_ID, OnChanges, SimpleChanges, DoCheck, HostListener
5+
LOCALE_ID, OnChanges, SimpleChanges, HostListener, OnInit
66
} from '@angular/core';
77
import {
88
ControlValueAccessor,
@@ -53,7 +53,7 @@ import { DateTimeUtil } from '../../date-common/util/date-time.util';
5353
{ provide: NG_VALIDATORS, useExisting: IgxDateTimeEditorDirective, multi: true }
5454
]
5555
})
56-
export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnChanges, DoCheck, Validator, ControlValueAccessor {
56+
export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnChanges, OnInit, Validator, ControlValueAccessor {
5757
/**
5858
* Locale settings used for value formatting.
5959
*
@@ -147,15 +147,13 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
147147
@Input(`igxDateTimeEditor`)
148148
public set inputFormat(value: string) {
149149
if (value) {
150-
this._format = value;
150+
this.setMask(value);
151+
this._inputFormat = value;
151152
}
152-
const mask = (this.inputFormat || DateTimeUtil.DEFAULT_INPUT_FORMAT)
153-
.replace(new RegExp(/(?=[^t])[\w]/, 'g'), '0');
154-
this.mask = mask.indexOf('tt') !== -1 ? mask.replace(new RegExp('tt', 'g'), 'LL') : mask;
155153
}
156154

157155
public get inputFormat(): string {
158-
return this._format || this._inputFormat;
156+
return this._inputFormat || this._defaultInputFormat;
159157
}
160158

161159
/**
@@ -212,13 +210,13 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
212210
@Output()
213211
public validationFailed = new EventEmitter<IgxDateTimeEditorEventArgs>();
214212

215-
private _format: string;
213+
private _inputFormat: string;
216214
private _oldValue: Date;
217215
private _dateValue: Date;
218216
private _onClear: boolean;
219217
private document: Document;
220218
private _isFocused: boolean;
221-
private _inputFormat: string;
219+
private _defaultInputFormat: string;
222220
private _value: Date | string;
223221
private _minValue: Date | string;
224222
private _maxValue: Date | string;
@@ -300,22 +298,20 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
300298
}
301299
}
302300

301+
public ngOnInit(): void {
302+
this.updateDefaultFormat();
303+
}
304+
303305
/** @hidden @internal */
304306
public ngOnChanges(changes: SimpleChanges) {
305-
if (changes['locale'] && !this._format) {
306-
this._inputFormat = DateTimeUtil.getDefaultInputFormat(this.locale);
307+
if (changes['locale'] && !changes['locale'].firstChange) {
308+
this.updateDefaultFormat();
307309
}
308-
if (changes['inputFormat']) {
309-
this.updateInputFormat();
310+
if (changes['inputFormat'] && !changes['inputFormat'].firstChange) {
311+
this.updateMask();
310312
}
311313
}
312314

313-
/** @hidden @internal */
314-
public ngDoCheck(): void {
315-
if (this._inputFormat !== this.inputFormat) {
316-
this.updateInputFormat();
317-
}
318-
}
319315

320316
/** Clear the input element value. */
321317
public clear(): void {
@@ -473,8 +469,15 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
473469
super.onBlur(value);
474470
}
475471

476-
/** @hidden @internal */
477-
public updateMask(): void {
472+
private updateDefaultFormat(): void {
473+
this._defaultInputFormat = DateTimeUtil.getDefaultInputFormat(this.locale);
474+
if (!this._inputFormat) {
475+
this.setMask(this.inputFormat);
476+
this.updateMask();
477+
}
478+
}
479+
480+
private updateMask(): void {
478481
if (!this.dateValue || !DateTimeUtil.isValidDate(this.dateValue)) {
479482
if (!this._isFocused) {
480483
this.inputValue = '';
@@ -506,6 +509,20 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
506509
}
507510
}
508511

512+
private setMask(inputFormat: string) {
513+
const oldFormat = this._inputDateParts?.map(p => p.format).join('');
514+
this._inputDateParts = DateTimeUtil.parseDateTimeFormat(inputFormat);
515+
inputFormat = this._inputDateParts.map(p => p.format).join('');
516+
const mask = (inputFormat || DateTimeUtil.DEFAULT_INPUT_FORMAT)
517+
.replace(new RegExp(/(?=[^t])[\w]/, 'g'), '0');
518+
this.mask = mask.indexOf('tt') !== -1 ? mask.replace(new RegExp('tt', 'g'), 'LL') : mask;
519+
520+
const placeholder = this.nativeElement.placeholder;
521+
if (!placeholder || oldFormat === placeholder) {
522+
this.renderer.setAttribute(this.nativeElement, 'placeholder', inputFormat);
523+
}
524+
}
525+
509526
private parseDate(val: string): Date | null {
510527
if (!val) {
511528
return null;
@@ -532,17 +549,6 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh
532549
return mask;
533550
}
534551

535-
private updateInputFormat(): void {
536-
const defPlaceholder = this.inputFormat || DateTimeUtil.getDefaultInputFormat(this.locale);
537-
this._inputDateParts = DateTimeUtil.parseDateTimeFormat(this.inputFormat);
538-
this.inputFormat = this._inputDateParts.map(p => p.format).join('');
539-
if (!this.nativeElement.placeholder || this._inputFormat !== this.inputFormat) {
540-
this.renderer.setAttribute(this.nativeElement, 'placeholder', defPlaceholder);
541-
}
542-
// TODO: fill in partial dates?
543-
this.updateMask();
544-
this._inputFormat = this.inputFormat;
545-
}
546552

547553
private valueInRange(value: Date): boolean {
548554
if (!value) {

0 commit comments

Comments
 (0)