diff --git a/apps/toolbox/project.json b/apps/toolbox/project.json
index cbd4bc8dc..8ace20a83 100644
--- a/apps/toolbox/project.json
+++ b/apps/toolbox/project.json
@@ -17,13 +17,15 @@
"ios": {
"executor": "@nativescript/nx:build",
"options": {
- "platform": "ios"
+ "platform": "ios",
+ "noHmr": true
}
},
"android": {
"executor": "@nativescript/nx:build",
"options": {
- "platform": "android"
+ "platform": "android",
+ "noHmr": true
}
},
"clean": {
diff --git a/apps/toolbox/src/main-page.xml b/apps/toolbox/src/main-page.xml
index d25cd1d7c..6c6d74cd3 100644
--- a/apps/toolbox/src/main-page.xml
+++ b/apps/toolbox/src/main-page.xml
@@ -9,6 +9,7 @@
+
diff --git a/apps/toolbox/src/pages/a11y.ts b/apps/toolbox/src/pages/a11y.ts
index d08cbe6fa..6c82fb442 100644
--- a/apps/toolbox/src/pages/a11y.ts
+++ b/apps/toolbox/src/pages/a11y.ts
@@ -26,10 +26,10 @@ export class AccessibilityModel extends Observable {
checkedChange(args) {
const checked = (args.object as Switch).checked;
console.log(checked);
- this.set('switchCheckedText', `${this.labelText} ${checked}`);
+ this.notifyPropertyChange('switchCheckedText', `${this.labelText} ${checked}`);
// prettier-ignore
- this.set('largeImageSrc', checked ?
+ this.notifyPropertyChange('largeImageSrc', checked ?
'https://i.picsum.photos/id/669/5000/5000.jpg?hmac=VlpchW0ODhflKm0SKOYQrc8qysLWbqKmDS1MGT9apAc' :
'https://i.picsum.photos/id/684/5000/5000.jpg?hmac=loiXO_OQ-y86XY_hc7p3qJdY39fSd9CuDM0iA_--P4Q');
}
diff --git a/apps/toolbox/src/pages/datepicker.ts b/apps/toolbox/src/pages/datepicker.ts
new file mode 100644
index 000000000..73bd0ddcf
--- /dev/null
+++ b/apps/toolbox/src/pages/datepicker.ts
@@ -0,0 +1,31 @@
+import { Page, ImageSource, Observable, EventData, knownFolders, path, Switch, DatePicker } from '@nativescript/core';
+
+let page: Page;
+
+export function navigatingTo(args: EventData) {
+ page = args.object;
+ page.bindingContext = new SampleData();
+}
+
+export class SampleData extends Observable {
+ displayDate = {
+ day: new Date().getDate(),
+ month: new Date().getMonth(),
+ year: new Date().getFullYear(),
+ hour: new Date().getHours(),
+ minute: new Date().getMinutes(),
+ second: new Date().getSeconds(),
+ };
+ showTime = true;
+
+ dateChange(args) {
+ console.log('dateChange:', (args.object).date);
+ }
+
+ checkedChange(args) {
+ const checked = (args.object as Switch).checked;
+ this.showTime = checked;
+ console.log('this.showTime:', this.showTime);
+ this.notifyPropertyChange('showTime', this.showTime);
+ }
+}
diff --git a/apps/toolbox/src/pages/datepicker.xml b/apps/toolbox/src/pages/datepicker.xml
new file mode 100644
index 000000000..1ee24af21
--- /dev/null
+++ b/apps/toolbox/src/pages/datepicker.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/toolbox/src/pages/image-async.ts b/apps/toolbox/src/pages/image-async.ts
index 893cd4d23..0df2b77c1 100644
--- a/apps/toolbox/src/pages/image-async.ts
+++ b/apps/toolbox/src/pages/image-async.ts
@@ -22,12 +22,12 @@ export class SampleData extends Observable {
const saved = results[0];
const base64Result = results[1];
if (saved) {
- this.set('savedData', tempFile);
+ this.notifyPropertyChange('savedData', tempFile);
console.log('ImageAsset saved', saved, tempFile);
}
console.log('base64', base64Result);
console.log(results[2].width, results[2].height);
- this.set('resizedImage', results[2]);
+ this.notifyPropertyChange('resizedImage', results[2]);
} catch (e) {
console.log('Failed to save ImageAsset');
}
diff --git a/apps/toolbox/src/pages/visibility-vs-hidden.ts b/apps/toolbox/src/pages/visibility-vs-hidden.ts
index 804351aa8..3b8c41fb1 100644
--- a/apps/toolbox/src/pages/visibility-vs-hidden.ts
+++ b/apps/toolbox/src/pages/visibility-vs-hidden.ts
@@ -21,12 +21,12 @@ export class VisibilityVsHiddenModel extends Observable {
if (this.currentVisibilityIndex === 3) {
this.currentVisibilityIndex = 0;
}
- this.set('currentVisibility', this.visibilityOptions[this.currentVisibilityIndex]);
- this.set('currentVisibilityType', `Current Visibility: ${this.visibilityOptions[this.currentVisibilityIndex]}`);
+ this.notifyPropertyChange('currentVisibility', this.visibilityOptions[this.currentVisibilityIndex]);
+ this.notifyPropertyChange('currentVisibilityType', `Current Visibility: ${this.visibilityOptions[this.currentVisibilityIndex]}`);
}
toggleHidden() {
- this.set('currentHidden', !this.currentHidden);
- this.set('currentHiddenType', `Current Hidden: ${this.currentHidden}`);
+ this.notifyPropertyChange('currentHidden', !this.currentHidden);
+ this.notifyPropertyChange('currentHiddenType', `Current Hidden: ${this.currentHidden}`);
}
}
diff --git a/apps/ui/project.json b/apps/ui/project.json
index 01150a335..217179afe 100644
--- a/apps/ui/project.json
+++ b/apps/ui/project.json
@@ -17,13 +17,15 @@
"ios": {
"executor": "@nativescript/nx:build",
"options": {
- "platform": "ios"
+ "platform": "ios",
+ "noHmr": true
}
},
"android": {
"executor": "@nativescript/nx:build",
"options": {
- "platform": "android"
+ "platform": "android",
+ "noHmr": true
}
},
"clean": {
diff --git a/packages/core/ui/date-picker/date-picker-common.ts b/packages/core/ui/date-picker/date-picker-common.ts
index 166e14059..451b1ecc1 100644
--- a/packages/core/ui/date-picker/date-picker-common.ts
+++ b/packages/core/ui/date-picker/date-picker-common.ts
@@ -1,5 +1,6 @@
import { DatePicker as DatePickerDefinition } from '.';
import { View, CSSType } from '../core/view';
+import { booleanConverter } from '../core/view-base';
import { Property } from '../core/properties';
const defaultDate = new Date();
@@ -10,10 +11,14 @@ export class DatePickerBase extends View implements DatePickerDefinition {
public year: number;
public month: number;
public day: number;
+ public hour: number;
+ public minute: number;
+ public second: number;
public maxDate: Date;
public minDate: Date;
public date: Date;
public iosPreferredDatePickerStyle: number;
+ public showTime: boolean;
}
DatePickerBase.prototype.recycleNativeView = 'auto';
@@ -39,6 +44,27 @@ export const dayProperty = new Property({
});
dayProperty.register(DatePickerBase);
+export const hourProperty = new Property({
+ name: 'hour',
+ defaultValue: defaultDate.getHours(),
+ valueConverter: (v) => parseInt(v),
+});
+hourProperty.register(DatePickerBase);
+
+export const minuteProperty = new Property({
+ name: 'minute',
+ defaultValue: defaultDate.getMinutes(),
+ valueConverter: (v) => parseInt(v),
+});
+minuteProperty.register(DatePickerBase);
+
+export const secondProperty = new Property({
+ name: 'second',
+ defaultValue: defaultDate.getSeconds(),
+ valueConverter: (v) => parseInt(v),
+});
+secondProperty.register(DatePickerBase);
+
// TODO: Make CoercibleProperties
export const maxDateProperty = new Property({
name: 'maxDate',
@@ -62,6 +88,13 @@ export const dateProperty = new Property({
});
dateProperty.register(DatePickerBase);
+export const showTimeProperty = new Property({
+ name: 'showTime',
+ defaultValue: false,
+ valueConverter: (v) => booleanConverter(v),
+});
+showTimeProperty.register(DatePickerBase);
+
export const iosPreferredDatePickerStyleProperty = new Property({
name: 'iosPreferredDatePickerStyle',
defaultValue: 0,
diff --git a/packages/core/ui/date-picker/index.android.ts b/packages/core/ui/date-picker/index.android.ts
index 23413e66d..c0bed9e73 100644
--- a/packages/core/ui/date-picker/index.android.ts
+++ b/packages/core/ui/date-picker/index.android.ts
@@ -1,4 +1,6 @@
import { DatePickerBase, yearProperty, monthProperty, dayProperty, dateProperty, maxDateProperty, minDateProperty } from './date-picker-common';
+import { TimePicker } from '../time-picker';
+import { StackLayout } from '../layouts/stack-layout';
export * from './date-picker-common';
@@ -40,8 +42,15 @@ function initializeDateChangedListener(): void {
dateChanged = true;
}
- if (dateChanged) {
- dateProperty.nativeValueChange(owner, new Date(year, month, day));
+ if (dateChanged || (owner.showTime && owner.timePicker)) {
+ let newDate: Date;
+ if (owner.showTime && owner.timePicker) {
+ const dateTime = owner.timePicker.time;
+ newDate = new Date(year, month, day, dateTime.getHours(), dateTime.getMinutes(), dateTime.getSeconds(), dateTime.getMilliseconds());
+ } else {
+ newDate = new Date(year, month, day);
+ }
+ dateProperty.nativeValueChange(owner, newDate);
}
}
}
@@ -51,6 +60,7 @@ function initializeDateChangedListener(): void {
export class DatePicker extends DatePickerBase {
nativeViewProtected: android.widget.DatePicker;
+ timePicker: TimePicker;
public createNativeView() {
const picker = new android.widget.DatePicker(this._context);
@@ -66,9 +76,21 @@ export class DatePicker extends DatePickerBase {
const listener = new DateChangedListener(this);
nativeView.init(this.year, this.month - 1, this.day, listener);
(nativeView).listener = listener;
+ if (this.showTime) {
+ this.timePicker = new TimePicker();
+ this.timePicker.width = this.width;
+ this.timePicker.height = this.height;
+ this.timePicker.on('timeChange', (args) => {
+ this.updateNativeDate();
+ });
+ (this.parent).addChild(this.timePicker);
+ }
}
public disposeNativeView() {
+ if (this.timePicker) {
+ this.timePicker.disposeNativeView();
+ }
(this.nativeViewProtected).listener.owner = null;
super.disposeNativeView();
}
@@ -78,7 +100,12 @@ export class DatePicker extends DatePickerBase {
const year = typeof this.year === 'number' ? this.year : nativeView.getYear();
const month = typeof this.month === 'number' ? this.month - 1 : nativeView.getMonth();
const day = typeof this.day === 'number' ? this.day : nativeView.getDayOfMonth();
- this.date = new Date(year, month, day);
+ if (this.showTime && this.timePicker) {
+ const time = this.timePicker.time || new Date();
+ this.date = new Date(year, month, day, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
+ } else {
+ this.date = new Date(year, month, day);
+ }
}
[yearProperty.setNative](value: number) {
diff --git a/packages/core/ui/date-picker/index.ios.ts b/packages/core/ui/date-picker/index.ios.ts
index 69267ccd9..5c80f53de 100644
--- a/packages/core/ui/date-picker/index.ios.ts
+++ b/packages/core/ui/date-picker/index.ios.ts
@@ -1,4 +1,4 @@
-import { DatePickerBase, yearProperty, monthProperty, dayProperty, dateProperty, maxDateProperty, minDateProperty } from './date-picker-common';
+import { DatePickerBase, yearProperty, monthProperty, dayProperty, dateProperty, maxDateProperty, minDateProperty, hourProperty, minuteProperty, secondProperty, showTimeProperty, iosPreferredDatePickerStyleProperty } from './date-picker-common';
import { colorProperty } from '../styling/style-properties';
import { Color } from '../../color';
import { Device } from '../../platform';
@@ -14,7 +14,7 @@ export class DatePicker extends DatePickerBase {
public createNativeView() {
const picker = UIDatePicker.new();
- picker.datePickerMode = UIDatePickerMode.Date;
+ picker.datePickerMode = this.showTime ? UIDatePickerMode.DateAndTime : UIDatePickerMode.Date;
if (SUPPORT_DATE_PICKER_STYLE) {
picker.preferredDatePickerStyle = this.iosPreferredDatePickerStyle;
}
@@ -38,27 +38,61 @@ export class DatePicker extends DatePickerBase {
return this.nativeViewProtected;
}
+ [showTimeProperty.setNative](value: boolean) {
+ this.showTime = value;
+ if (this.nativeViewProtected) {
+ this.nativeViewProtected.datePickerMode = this.showTime ? UIDatePickerMode.DateAndTime : UIDatePickerMode.Date;
+ }
+ }
+
+ [iosPreferredDatePickerStyleProperty.setNative](value: number) {
+ this.iosPreferredDatePickerStyle = value;
+ if (this.nativeViewProtected) {
+ if (SUPPORT_DATE_PICKER_STYLE) {
+ this.nativeViewProtected.preferredDatePickerStyle = this.iosPreferredDatePickerStyle;
+ }
+ }
+ }
+
[yearProperty.setNative](value: number) {
- this.date = new Date(value, this.month - 1, this.day);
+ this.date = new Date(value, this.month - 1, this.day, this.hour || 0, this.minute || 0, this.second || 0);
}
[monthProperty.setNative](value: number) {
- this.date = new Date(this.year, value - 1, this.day);
+ this.date = new Date(this.year, value - 1, this.day, this.hour || 0, this.minute || 0, this.second || 0);
}
[dayProperty.setNative](value: number) {
- this.date = new Date(this.year, this.month - 1, value);
+ this.date = new Date(this.year, this.month - 1, value, this.hour || 0, this.minute || 0, this.second || 0);
+ }
+
+ [hourProperty.setNative](value: number) {
+ this.date = new Date(this.year, this.month - 1, this.day, value, this.minute || 0, this.second || 0);
+ }
+
+ [minuteProperty.setNative](value: number) {
+ this.date = new Date(this.year, this.month - 1, this.day, this.hour || 0, value, this.second || 0);
+ }
+
+ [secondProperty.setNative](value: number) {
+ this.date = new Date(this.year, this.month - 1, this.day, this.hour || 0, this.minute || 0, value);
}
[dateProperty.setNative](value: Date) {
const picker = this.nativeViewProtected;
- const comps = NSCalendar.currentCalendar.componentsFromDate(NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay, picker.date);
+ const comps = NSCalendar.currentCalendar.componentsFromDate(NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.HourCalendarUnit | NSCalendarUnit.MinuteCalendarUnit | NSCalendarUnit.SecondCalendarUnit, picker.date);
comps.year = value.getFullYear();
comps.month = value.getMonth() + 1;
comps.day = value.getDate();
+ comps.hour = value.getHours();
+ comps.minute = value.getMinutes();
+ comps.second = value.getSeconds();
this.year = comps.year;
this.month = comps.month;
this.day = comps.day;
+ this.hour = comps.hour;
+ this.minute = comps.minute;
+ this.second = comps.second;
picker.setDateAnimated(NSCalendar.currentCalendar.dateFromComponents(comps), false);
}
@@ -103,13 +137,13 @@ class UIDatePickerChangeHandlerImpl extends NSObject {
}
public valueChanged(sender: UIDatePicker) {
- const comps = NSCalendar.currentCalendar.componentsFromDate(NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay, sender.date);
-
const owner = this._owner.get();
if (!owner) {
return;
}
+ const comps = NSCalendar.currentCalendar.componentsFromDate(NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.HourCalendarUnit | NSCalendarUnit.MinuteCalendarUnit | NSCalendarUnit.SecondCalendarUnit, sender.date);
+
let dateChanged = false;
if (comps.year !== owner.year) {
yearProperty.nativeValueChange(owner, comps.year);
@@ -126,8 +160,23 @@ class UIDatePickerChangeHandlerImpl extends NSObject {
dateChanged = true;
}
+ if (comps.hour !== owner.hour) {
+ hourProperty.nativeValueChange(owner, comps.hour);
+ dateChanged = true;
+ }
+
+ if (comps.minute !== owner.minute) {
+ minuteProperty.nativeValueChange(owner, comps.minute);
+ dateChanged = true;
+ }
+
+ if (comps.second !== owner.second) {
+ secondProperty.nativeValueChange(owner, comps.second);
+ dateChanged = true;
+ }
+
if (dateChanged) {
- dateProperty.nativeValueChange(owner, new Date(comps.year, comps.month - 1, comps.day));
+ dateProperty.nativeValueChange(owner, new Date(comps.year, comps.month - 1, comps.day, comps.hour, comps.minute, comps.second));
}
}