Skip to content

Commit b0d9acf

Browse files
committed
fix: issue with ng-validation
1 parent d0aefd1 commit b0d9acf

File tree

6 files changed

+127
-61
lines changed

6 files changed

+127
-61
lines changed

src/angular/nativescript-datetimepicker.accessors.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,13 @@ const DATE_TIME_PICKERS_VALUE_ACCESSOR = {
3939
"date-picker-field[ngModel],date-picker-field[formControlName],date-picker-field[formControl]",
4040
providers: [DATE_PICKER_VALUE_ACCESSOR],
4141
host: {
42-
"(dateChange)": "onChange($event.value)",
42+
"(dateChange)": "handleDateChange($event)",
43+
"(datePickerOpened)": "handleDatePickerOpened($event)",
44+
"(datePickerClosed)": "handleDatePickerClosed($event)"
4345
},
4446
})
4547
export class DatePickerValueAccessor extends BaseValueAccessor<DatePickerField> {
48+
private _hasBeenOpened = false;
4649
constructor(elementRef: ElementRef) {
4750
super(elementRef.nativeElement);
4851
}
@@ -51,6 +54,20 @@ export class DatePickerValueAccessor extends BaseValueAccessor<DatePickerField>
5154
const normalized = super.normalizeValue(value);
5255
this.view.date = normalized;
5356
}
57+
58+
handleDateChange(args: any) {
59+
if (this._hasBeenOpened) {
60+
this.onChange(args.value);
61+
}
62+
}
63+
64+
handleDatePickerOpened(args: any) {
65+
this._hasBeenOpened = true;
66+
}
67+
68+
handleDatePickerClosed(args: any) {
69+
this.onTouched();
70+
}
5471
}
5572

5673
/**
@@ -69,10 +86,13 @@ export class DatePickerValueAccessor extends BaseValueAccessor<DatePickerField>
6986
"time-picker-field[ngModel],time-picker-field[formControlName],time-picker-field[formControl]",
7087
providers: [TIME_PICKER_VALUE_ACCESSOR],
7188
host: {
72-
"(timeChange)": "onChange($event.value)",
89+
"(timeChange)": "handleTimeChange($event)",
90+
"(timePickerOpened)": "handleTimePickerOpened($event)",
91+
"(timePickerClosed)": "handleTimePickerClosed($event)"
7392
},
7493
})
7594
export class TimePickerValueAccessor extends BaseValueAccessor<TimePickerField> {
95+
private _hasBeenOpened = false;
7696
constructor(elementRef: ElementRef) {
7797
super(elementRef.nativeElement);
7898
}
@@ -81,6 +101,20 @@ export class TimePickerValueAccessor extends BaseValueAccessor<TimePickerField>
81101
const normalized = super.normalizeValue(value);
82102
this.view.time = normalized;
83103
}
104+
105+
handleTimeChange(args: any) {
106+
if (this._hasBeenOpened) {
107+
this.onChange(args.value);
108+
}
109+
}
110+
111+
handleTimePickerOpened(args: any) {
112+
this._hasBeenOpened = true;
113+
}
114+
115+
handleTimePickerClosed(args: any) {
116+
this.onTouched();
117+
}
84118
}
85119

86120
/**
@@ -99,10 +133,15 @@ export class TimePickerValueAccessor extends BaseValueAccessor<TimePickerField>
99133
"date-time-picker-fields[ngModel],date-time-picker-fields[formControlName],date-time-picker-fields[formControl]",
100134
providers: [DATE_TIME_PICKERS_VALUE_ACCESSOR],
101135
host: {
102-
"(dateChange)": "onChange($event.value)",
136+
"(dateChange)": "handleDateChange($event)",
137+
"(datePickerOpened)": "handlePickerOpened($event)",
138+
"(datePickerClosed)": "handlePickerClosed($event)",
139+
"(timePickerOpened)": "handlePickerOpened($event)",
140+
"(timePickerClosed)": "handlePickerClosed($event)"
103141
},
104142
})
105143
export class DateTimePickersValueAccessor extends BaseValueAccessor<DateTimePickerFields> {
144+
private _hasBeenOpened = false;
106145
constructor(elementRef: ElementRef) {
107146
super(elementRef.nativeElement);
108147
}
@@ -111,4 +150,18 @@ export class DateTimePickersValueAccessor extends BaseValueAccessor<DateTimePick
111150
const normalized = super.normalizeValue(value);
112151
this.view.date = normalized;
113152
}
153+
154+
handleDateChange(args: any) {
155+
if (this._hasBeenOpened) {
156+
this.onChange(args.value);
157+
}
158+
}
159+
160+
handlePickerOpened(args: any) {
161+
this._hasBeenOpened = true;
162+
}
163+
164+
handlePickerClosed(args: any) {
165+
this.onTouched();
166+
}
114167
}

src/datetimepicker.android.ts

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,7 @@ import {
66
DatePickerOptions, TimePickerOptions, PickerOptions
77
} from "./datetimepicker.common";
88

9-
interface DialogClickListener {
10-
new(datePicker: any, dateTime: Date, callback: Function): android.content.DialogInterface.OnClickListener;
11-
}
12-
13-
interface DialogDismissListener {
14-
new(callback: Function): android.content.DialogInterface.OnDismissListener;
15-
}
16-
17-
let DialogClickListener: DialogClickListener;
18-
let DialogDismissListener: DialogDismissListener;
9+
let DialogListener: any;
1910
let AppCompatNamespace: any;
2011
declare let global: any;
2112

@@ -30,13 +21,14 @@ function initializeAppCompatNamespace(): void {
3021
}
3122
}
3223

33-
function initializeDialogClickListener(): void {
34-
if (DialogClickListener) {
24+
function initializeDialogListener(): void {
25+
if (DialogListener) {
3526
return;
3627
}
3728

38-
@Interfaces([android.content.DialogInterface.OnClickListener])
39-
class DialogClickListenerImpl extends java.lang.Object implements android.content.DialogInterface.OnClickListener {
29+
@Interfaces([android.content.DialogInterface.OnClickListener, android.content.DialogInterface.OnDismissListener])
30+
class DialogListenerImpl extends java.lang.Object implements android.content.DialogInterface.OnClickListener, android.content.DialogInterface.OnDismissListener {
31+
private _isClicked = false;
4032
constructor(public nativePicker: any, public dateTime: Date, public callback: Function) {
4133
super();
4234
return global.__native(this);
@@ -46,6 +38,7 @@ function initializeDialogClickListener(): void {
4638
const callback = this.callback;
4739
const dateTime = this.dateTime;
4840
const nativePicker = this.nativePicker;
41+
this._isClicked = true;
4942
switch (which) {
5043
case android.content.DialogInterface.BUTTON_POSITIVE: {
5144
if (nativePicker instanceof android.widget.DatePicker) {
@@ -63,30 +56,19 @@ function initializeDialogClickListener(): void {
6356
}
6457
callback(null);
6558
}
66-
}
67-
68-
DialogClickListener = DialogClickListenerImpl;
69-
}
70-
71-
function initializeDialogDismissListener(): void {
72-
if (DialogDismissListener) {
73-
return;
74-
}
75-
76-
@Interfaces([android.content.DialogInterface.OnDismissListener])
77-
class DialogDismissListenerImpl extends java.lang.Object implements android.content.DialogInterface.OnDismissListener {
78-
constructor(public callback: Function) {
79-
super();
80-
return global.__native(this);
81-
}
8259

8360
onDismiss(dialog: android.content.DialogInterface) {
61+
if (this._isClicked) {
62+
// The Picker is dismissed due to a button click,
63+
// so the callback is already called.
64+
return;
65+
}
8466
const callback = this.callback;
8567
callback(null);
8668
}
8769
}
8870

89-
DialogDismissListener = DialogDismissListenerImpl;
71+
DialogListener = DialogListenerImpl;
9072
}
9173

9274
export class DateTimePickerStyle extends DateTimePickerStyleBase {
@@ -167,8 +149,7 @@ export class DateTimePicker extends DateTimePickerBase {
167149
}
168150

169151
static _createNativeDialog(nativePicker: android.view.View, options: PickerOptions, value: Date, callback: Function): android.app.AlertDialog.Builder {
170-
initializeDialogClickListener();
171-
initializeDialogDismissListener();
152+
initializeDialogListener();
172153
initializeAppCompatNamespace();
173154
DateTimePicker._initializeTextResources(options.context);
174155
const context = options.context;
@@ -179,16 +160,15 @@ export class DateTimePicker extends DateTimePickerBase {
179160
dateTime = (nativePicker instanceof android.widget.DatePicker) ? getDateToday() : getDateNow();
180161
}
181162
const alertDialog = new android.app.AlertDialog.Builder(context);
182-
const dialogClickListener = new DialogClickListener(nativePicker, dateTime, callback);
183-
const dialogDismissListener = new DialogDismissListener(callback);
163+
const dialogListener = new DialogListener(nativePicker, dateTime, callback);
184164
if (options.title) {
185165
alertDialog.setTitle(options.title);
186166
}
187-
alertDialog.setOnDismissListener(dialogDismissListener);
167+
alertDialog.setOnDismissListener(dialogListener);
188168
const cancelButtonText = options.cancelButtonText ? options.cancelButtonText : this._defaultCancelText;
189169
const okButtonText = options.okButtonText ? options.okButtonText : this._defaultOkText;
190-
alertDialog.setNegativeButton(cancelButtonText, dialogClickListener);
191-
alertDialog.setPositiveButton(okButtonText, dialogClickListener);
170+
alertDialog.setNegativeButton(cancelButtonText, dialogListener);
171+
alertDialog.setPositiveButton(okButtonText, dialogListener);
192172
alertDialog.setView(nativePicker);
193173
return alertDialog;
194174
}

src/ui/date-picker-field.common.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Property, CSSType } from "tns-core-modules/ui/core/view";
1+
import { Property, CSSType, EventData } from "tns-core-modules/ui/core/view";
22
import { DateTimePicker, DateTimePickerStyle } from "../datetimepicker";
33
import { DatePickerField as DatePickerFieldDefinition } from "./date-picker-field";
44
import { LocalizationUtils } from "../utils/localization-utils";
5-
import { getDateToday } from "../utils/date-utils";
5+
import { getDateToday, dateComparer } from "../utils/date-utils";
66
import { PickerFieldBase } from "./picker-field-base";
77

88
@CSSType("DatePickerField")
@@ -12,6 +12,8 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
1212
public date: Date;
1313
public dateFormat: string;
1414
public pickerDefaultDate: Date;
15+
public static datePickerOpenedEvent = "datePickerOpened";
16+
public static datePickerClosedEvent = "datePickerClosed";
1517

1618
private _nativeLocale: any;
1719
private _nativeDateFormatter: any;
@@ -63,10 +65,20 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
6365
if (result) {
6466
this.date = result;
6567
}
68+
let args = <EventData>{
69+
eventName: DatePickerFieldBase.datePickerClosedEvent,
70+
object: this
71+
};
72+
this.notify(args);
6673
})
6774
.catch((err) => {
6875
console.log('DatePickerField Error: ' + err);
6976
});
77+
let args = <EventData>{
78+
eventName: DatePickerFieldBase.datePickerOpenedEvent,
79+
object: this
80+
};
81+
this.notify(args);
7082
}
7183

7284
public updateText() {
@@ -112,10 +124,6 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
112124
}
113125
}
114126

115-
export function dateComparer(x: Date, y: Date): boolean {
116-
return x <= y && x >= y;
117-
}
118-
119127
export function dateValueConverter(v: any): Date {
120128
return new Date(v);
121129
}

src/ui/date-time-picker-fields.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { Property, CSSType } from "tns-core-modules/ui/core/view";
1+
import { Property, CSSType, EventData } from "tns-core-modules/ui/core/view";
22
import { PropertyChangeData } from "tns-core-modules/data/observable";
33
import { DateTimePickerFields as DateTimePickerFieldsDefinition } from "./date-time-picker-fields";
44
import { GridLayout, ItemSpec } from "tns-core-modules/ui/layouts/grid-layout";
55
import { Orientation } from "tns-core-modules/ui/layouts/stack-layout";
66
import { DatePickerField } from "./date-picker-field";
77
import { TimePickerField } from "./time-picker-field";
8-
import { getDateNow, clearTime } from "../utils/date-utils";
8+
import { getDateNow, clearTime, dateComparer } from "../utils/date-utils";
99

1010
@CSSType("DateTimePickerFields")
1111
export class DateTimePickerFields extends GridLayout implements DateTimePickerFieldsDefinition {
@@ -241,6 +241,17 @@ export class DateTimePickerFields extends GridLayout implements DateTimePickerFi
241241
super.disposeNativeView();
242242
}
243243

244+
public addEventListener(eventNames: string, callback: (data: EventData) => void, thisArg?: Object) {
245+
super.addEventListener(eventNames, callback, thisArg);
246+
this.dateField.addEventListener(eventNames, callback, thisArg);
247+
this.timeField.addEventListener(eventNames, callback, thisArg);
248+
}
249+
public removeEventListener(eventNames: string, callback?: any, thisArg?: Object) {
250+
super.removeEventListener(eventNames, callback, thisArg);
251+
this.dateField.removeEventListener(eventNames, callback, thisArg);
252+
this.timeField.removeEventListener(eventNames, callback, thisArg);
253+
}
254+
244255
private _updateHandlers(subscribe: boolean) {
245256
if (subscribe) {
246257
this._dateChangeHandler = this._dateChangeHandler || ((args: PropertyChangeData) => {
@@ -299,10 +310,6 @@ export class DateTimePickerFields extends GridLayout implements DateTimePickerFi
299310
}
300311
}
301312

302-
export function dateComparer(x: Date, y: Date): boolean {
303-
return x <= y && x >= y;
304-
}
305-
306313
export function dateValueConverter(v: any): Date {
307314
return new Date(v);
308315
}

src/ui/time-picker-field.common.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
import { Property, CSSType } from "tns-core-modules/ui/core/view";
1+
import { Property, CSSType, EventData } from "tns-core-modules/ui/core/view";
22
import { DateTimePicker, DateTimePickerStyle } from "../datetimepicker";
33
import { TimePickerField as TimePickerFieldDefinition } from "./time-picker-field";
44
import { LocalizationUtils } from "../utils/localization-utils";
5-
import { getDateNow } from "../utils/date-utils";
5+
import { getDateNow, dateComparer } from "../utils/date-utils";
66
import { PickerFieldBase } from "./picker-field-base";
77

88
@CSSType("TimePickerField")
99
export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFieldDefinition {
1010
public time: Date;
1111
public timeFormat: string;
1212
public pickerDefaultTime: Date;
13+
public static timePickerOpenedEvent = "timePickerOpened";
14+
public static timePickerClosedEvent = "timePickerClosed";
1315

1416
private _nativeLocale: any;
1517
private _nativeTimeFormatter: any;
1618

1719
public static timeProperty = new Property<TimePickerFieldBase, Date>({
1820
name: "time",
19-
equalityComparer: timeComparer,
21+
equalityComparer: dateComparer,
2022
valueConverter: timeValueConverter,
2123
valueChanged: TimePickerFieldBase.timePropertyChanged
2224
});
@@ -29,7 +31,7 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
2931
public static pickerDefaultTimeProperty = new Property<TimePickerFieldBase, Date>({
3032
name: "pickerDefaultTime",
3133
defaultValue: getDateNow(),
32-
equalityComparer: timeComparer,
34+
equalityComparer: dateComparer,
3335
valueConverter: timeValueConverter
3436
});
3537

@@ -48,10 +50,20 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
4850
if (result) {
4951
this.time = result;
5052
}
53+
let args = <EventData>{
54+
eventName: TimePickerFieldBase.timePickerClosedEvent,
55+
object: this
56+
};
57+
this.notify(args);
5158
})
5259
.catch((err) => {
5360
console.log('TimePickerField Error: ' + err);
5461
});
62+
let args = <EventData>{
63+
eventName: TimePickerFieldBase.timePickerOpenedEvent,
64+
object: this
65+
};
66+
this.notify(args);
5567
}
5668

5769
public updateText() {
@@ -101,10 +113,6 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
101113
}
102114
}
103115

104-
export function timeComparer(x: Date, y: Date): boolean {
105-
return x <= y && x >= y;
106-
}
107-
108116
// Creates a date for today with the time represented in the timeString in ISO 8601 formats
109117
// as specified here: https://en.wikipedia.org/wiki/ISO_8601#Times:
110118
// 1)hh:mm:ss.sss --- 2)hhmmss.sss --- 3)hh:mm:ss --- 4)hhmmss --- 5)hh:mm --- 6)hhmm --- 7)hh

0 commit comments

Comments
 (0)