diff --git a/.travis.yml b/.travis.yml
index 65363f1..457934e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,7 +26,7 @@ matrix:
- stage: "lint"
language: node_js
os: linux
- node_js: "8"
+ node_js: "10"
script:
- cd src && npm run ci.tslint
- cd ../demo && npm run ci.tslint
@@ -37,147 +37,146 @@ matrix:
env:
- WebpackiOS="12.0"
- Type="VanillaJS"
- osx_image: xcode10.0
+ osx_image: xcode10.2
language: node_js
- node_js: "8"
+ node_js: "10"
jdk: oraclejdk8
before_script: pod repo update
script:
- cd src && npm run build
- - cd ../demo && npm i && tns build ios --bundle --env.uglify --copy-to "./outputs/demo.app"
+ - cd ../demo && npm i && tns build ios --env.uglify --copy-to "./outputs/demo.app"
- cd $IOS_PACKAGE_FOLDER_JS && zip -r $IOS_PACKAGE_JS demo.app
- "curl -u $SAUCE_USER:$SAUCE_KEY -X POST -H 'Content-Type: application/octet-stream' $IOS_SAUCE_STORAGE/$IOS_PACKAGE_JS?overwrite=true --data-binary @$IOS_PACKAGE_FOLDER_JS/$IOS_PACKAGE_JS"
- os: osx
env:
- WebpackiOS="12.0"
- Type="VueJS"
- osx_image: xcode10.0
+ osx_image: xcode10.2
language: node_js
- node_js: "8"
+ node_js: "10"
jdk: oraclejdk8
before_script: pod repo update
script:
- cd src && npm run build
- - cd ../demo-vue && npm i && tns build ios --bundle --env.uglify --copy-to "./outputs/demovue.app"
+ - cd ../demo-vue && npm i && tns build ios --env.uglify --copy-to "./outputs/demovue.app"
- cd $IOS_PACKAGE_FOLDER_VUE && zip -r $IOS_PACKAGE_VUE demovue.app
- "curl -u $SAUCE_USER:$SAUCE_KEY -X POST -H 'Content-Type: application/octet-stream' $IOS_SAUCE_STORAGE/$IOS_PACKAGE_VUE?overwrite=true --data-binary @$IOS_PACKAGE_FOLDER_VUE/$IOS_PACKAGE_VUE"
- os: osx
env:
- WebpackiOS="12.0"
- Type="Angular"
- osx_image: xcode10.0
+ osx_image: xcode10.2
language: node_js
- node_js: "8"
+ node_js: "10"
jdk: oraclejdk8
before_script: pod repo update
script:
- cd src && npm run build && npm pack
- cd ../demo-angular && tns plugin add ../src/*.tgz
- - npm i && tns build ios --bundle --env.uglify --env.aot --copy-to "./outputs/demoangular.app"
+ - npm i && tns build ios --env.uglify --env.aot --copy-to "./outputs/demoangular.app"
- cd $IOS_PACKAGE_FOLDER_NG && zip -r $IOS_PACKAGE_NG demoangular.app
- "curl -u $SAUCE_USER:$SAUCE_KEY -X POST -H 'Content-Type: application/octet-stream' $IOS_SAUCE_STORAGE/$IOS_PACKAGE_NG?overwrite=true --data-binary @$IOS_PACKAGE_FOLDER_NG/$IOS_PACKAGE_NG"
- language: android
os: linux
+ dist: trusty
env:
- WebpackAndroid="28"
- Type="VanillaJS"
jdk: oraclejdk8
- before_install: nvm install 8
+ before_install: nvm install 10
script:
- cd src && npm run build
- - cd ../demo && npm i && tns build android --bundle --env.uglify --env.snapshot --copy-to "./outputs/app-debug.apk"
+ - cd ../demo && npm i && tns build android --env.uglify --env.snapshot --copy-to "./outputs/app-debug.apk"
- "curl -u $SAUCE_USER:$SAUCE_KEY -X POST -H 'Content-Type: application/octet-stream' $ANDROID_SAUCE_STORAGE/$ANDROID_PACKAGE_JS?overwrite=true --data-binary @$ANDROID_PACKAGE_FOLDER_JS/app-debug.apk"
- language: android
os: linux
+ dist: trusty
env:
- WebpackAndroid="28"
- Type="VueJS"
jdk: oraclejdk8
- before_install: nvm install 8
+ before_install: nvm install 10
script:
- cd src && npm run build
- - cd ../demo-vue && npm i && tns build android --bundle --env.uglify --copy-to "./outputs/app-debug.apk"
+ - cd ../demo-vue && npm i && tns build android --env.uglify --copy-to "./outputs/app-debug.apk"
- "curl -u $SAUCE_USER:$SAUCE_KEY -X POST -H 'Content-Type: application/octet-stream' $ANDROID_SAUCE_STORAGE/$ANDROID_PACKAGE_VUE?overwrite=true --data-binary @$ANDROID_PACKAGE_FOLDER_VUE/app-debug.apk"
- language: android
os: linux
+ dist: trusty
env:
- WebpackAndroid="28"
- Type="Angular"
jdk: oraclejdk8
- before_install: nvm install 8
+ before_install: nvm install 10
script:
- cd src && npm run build
- cd ../publish && sh pack.sh
- cd ../demo-angular && tns plugin add ../publish/package/*.tgz
- - npm i && tns build android --bundle --env.uglify --env.snapshot --env.aot --copy-to "./outputs/app-debug.apk"
+ - npm i && tns build android --env.uglify --env.snapshot --env.aot --copy-to "./outputs/app-debug.apk"
- "curl -u $SAUCE_USER:$SAUCE_KEY -X POST -H 'Content-Type: application/octet-stream' $ANDROID_SAUCE_STORAGE/$ANDROID_PACKAGE_NG?overwrite=true --data-binary @$ANDROID_PACKAGE_FOLDER_NG/app-debug.apk"
- - language: android
+ - stage: "UI Tests"
env:
- - BuildAndroid="28"
- - Type="VanillaJS"
+ - Android="28"
+ - Type="Angular"
+ language: node_js
os: linux
- jdk: oraclejdk8
- before_install: nvm install 8.11.4
+ node_js: "10"
script:
- - cd src && npm run build
- - cd ../demo && tns build android
- - language: android
+ - npm i -g appium
+ - cd tests && npm i
+ - travis_wait travis_retry npm run e2e -- --runType android28 --sauceLab --appPath $ANDROID_PACKAGE_NG
+ - os: linux
env:
- - BuildAndroid="28"
- - Type="Angular"
+ - Android="28"
+ - Type="VanillaJS"
+ language: node_js
os: linux
- jdk: oraclejdk8
- before_install: nvm install 8.11.4
+ node_js: "10"
script:
- - cd src && npm run build
- - cd ../demo-angular && tns build android
- - os: osx
+ - npm i -g appium
+ - cd tests && npm i
+ - travis_wait travis_retry npm run e2e -- --runType android28 --sauceLab --appPath $ANDROID_PACKAGE_JS
+ - os: linux
env:
- - BuildiOS="12.0"
- - Xcode="10.0"
- - Type="VanillaJS"
- osx_image: xcode10.0
+ - Android="28"
+ - Type="VueJS"
language: node_js
- node_js: "8"
- jdk: oraclejdk8
- before_script: pod repo update
+ os: linux
+ node_js: "10"
script:
- - cd src && npm run build
- - cd ../demo && tns build ios --bundle --env.uglify
- - os: osx
+ - npm i -g appium
+ - cd tests && npm i
+ - travis_wait travis_retry npm run e2e -- --runType android28 --sauceLab --appPath $ANDROID_PACKAGE_VUE
+ - os: linux
env:
- - BuildiOS="12.0"
- - Xcode="10.0"
+ - iOS="12.0"
- Type="Angular"
- osx_image: xcode10.0
language: node_js
- node_js: "8"
- jdk: oraclejdk8
- before_script: pod repo update
+ node_js: "10"
script:
- - cd src && npm run build
- - cd ../demo-angular && tns build ios
- - stage: "UI Tests"
+ - npm i -g appium
+ - cd tests && npm i
+ - travis_wait travis_retry npm run e2e -- --runType sim.iPhoneX --sauceLab --appPath $IOS_PACKAGE_NG
+ - os: linux
env:
- - Android="24"
- - Type="Angular"
+ - iOS="12.0"
+ - Type="VueJS"
language: node_js
- os: linux
- node_js: "8"
+ node_js: "10"
script:
- npm i -g appium
- - cd demo-angular && npm i
- - travis_wait travis_retry npm run e2e -- --runType android24 --sauceLab --appPath $ANDROID_PACKAGE_NG
+ - cd tests && npm i
+ - travis_wait travis_retry npm run e2e -- --runType sim.iPhoneX --sauceLab --appPath $IOS_PACKAGE_VUE
- os: linux
env:
- iOS="12.0"
- - Type="Angular"
+ - Type="VanillaJS"
language: node_js
- node_js: "8"
+ node_js: "10"
script:
- npm i -g appium
- - cd demo-angular && npm i
- - travis_wait travis_retry npm run e2e -- --runType sim.iPhoneX --sauceLab --appPath $IOS_PACKAGE_NG
+ - cd tests && npm i
+ - travis_wait travis_retry npm run e2e -- --runType sim.iPhoneX --sauceLab --appPath $IOS_PACKAGE_JS
android:
components:
diff --git a/README.md b/README.md
index 8404294..b88d36a 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,19 @@
+# ALL NativeScript 7 Issues should be posted here: https://github.com/NativeScript/plugins/
+
+## NativeScript 7
+
+* Use `@nativescript/datetimepicker`: `~2.0.0`
+* [Source managed here](https://github.com/NativeScript/plugins)
+
+## If using 6 and below, see the following:
+
# NativeScript DateTimePicker
[](https://www.npmjs.com/package/nativescript-datetimepicker)
[](https://www.npmjs.com/package/nativescript-datetimepicker)
[](https://travis-ci.org/NativeScript/nativescript-datetimepicker)
-A [NativeScript](https://www.nativescript.org) plugin that provides ui elements for picking date and time. The plugin provides two fields - `DatePickerField` and `TimePickerField` - both are NativeScript Views that show selected date or time and allow picking another after being tapped. There is also a `DateTimePicker` class which provides static methods `pickDate` and `pickTime` that can be called to show the same dialog picker as the fields.
+A [NativeScript](https://www.nativescript.org) plugin that provides ui elements for picking date and time. The plugin provides UI elements for picking date and time - `DatePickerField`, `TimePickerField` and `DateTimePickerFields` - they are all NativeScript Views that show selected date and/or time and allow picking another after being tapped. There is also a `DateTimePicker` class which provides static methods `pickDate` and `pickTime` that can be called to show the same dialog picker as the fields.
- [Installation](#installation)
@@ -12,6 +21,7 @@ A [NativeScript](https://www.nativescript.org) plugin that provides ui elements
- [Usage](#usage)
- [Features](#features)
- [DatePickerField and TimePickerField](#datepickerfield-and-timepickerfield)
+ - [DateTimePickerFields](#datetimepickerfields)
- [DateTimePicker](#datetimepicker)
- [API](#api)
- [Contribute](#contribute)
@@ -32,7 +42,7 @@ tns plugin add nativescript-datetimepicker
No additional configuration required!
## Usage
-To use the `DatePickerField` and `TimePickerField` in markup you need to:
+To use one of the UI elements `DatePickerField`, `TimePickerField` or `DateTimePickerFields` in markup you need to:
- If you are developing a NativeScript Core app, you need to register the plugin namespace in the xml:
```xml
+
...
```
- If you are developing a NativeScript Angular app, you need to import the plugin module in the module of your component:
@@ -58,6 +69,7 @@ import { NativeScriptDateTimePickerModule } from "nativescript-datetimepicker/an
```html
+
```
- If you are developing a NativeScript Vue app, you need to install the plugin in you app.js file:
```js
@@ -69,6 +81,7 @@ Then you will be able to decrare the fields in the template of your component:
```html
+
```
## Features
@@ -78,23 +91,23 @@ The `DatePickerField` and the `TimePickerField` are NativeScript Views that exte
- Getting/Setting Date and Time
-The `DatePickerField` has a `date` property and the `TimePickerField` has a `time` property which can be used to get their current value. You can also set their value through markup. `DatePickerField`'s `date` property will just pass the string you provide as a parameter to the [Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date), while the `TimePickerField`'s `time` property can parse values in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) format. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L18), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L13) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L15) applications.
+The `DatePickerField` has a `date` property and the `TimePickerField` has a `time` property which can be used to get their current value. You can also set their value through markup. `DatePickerField`'s `date` property will just pass the string you provide as a parameter to the [Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date), while the `TimePickerField`'s `time` property can parse values in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) format. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L19), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L14) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L16) applications.
- TextField Features
-Both `DatePickerField` and `TimePickerField` extend `TextField`, so each `TextField` feature like the `hint` property, is also available for these fields. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L13), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L8) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L10) applications.
+Both `DatePickerField` and `TimePickerField` extend `TextField`, so each `TextField` feature like the `hint` property, is also available for these fields. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L15), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L10) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L12) applications.
- Picker Texts
-When one of the fields is tapped, a popup is opened. The popup has an OK and Cancel buttons and an optional title. Their text values are controlled respectively by the properties `pickerOkText`, `pickerCancelText` and `pickerTitle`. By default, the texts of the buttons OK and Cancel are `OK` and `Cancel` on iOS, and a localized version of OK and Cancel, dependent on the current setting of the device on Android. The `pickerTitle` is undefined. Changing these values is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L35), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L32) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L32) applications.
+When one of the fields is tapped, a popup is opened. The popup has an OK and Cancel buttons and an optional title. Their text values are controlled respectively by the properties `pickerOkText`, `pickerCancelText` and `pickerTitle`. By default, the texts of the buttons OK and Cancel are `OK` and `Cancel` on iOS, and a localized version of OK and Cancel, dependent on the current setting of the device on Android. The `pickerTitle` is undefined. Changing these values is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L27), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L22) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L24) applications.
- Localization
-By default the `DatePickerField` and the `TimePickerField` will use the current language and region settings of the device to determine their locale. The locale is used for the names of the months, for the date picking spinners order (the month selector can be either the first or the second spinner) and whether the time is in 12h or 24h format. Both fields have a `locale` property that accepts values in the format specified [here](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html) as Locale ID. For example, using `en_UK` will result in month names spinner in the middle and values between 0 and 23 for the hours, while using `en_US` will result in month names spinner on the left and values between 1 and 12 for the hours. Changing the locale is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L49), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L44) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L46) applications.
+By default the `DatePickerField` and the `TimePickerField` will use the current language and region settings of the device to determine their locale. The locale is used for the names of the months, for the date picking spinners order (the month selector can be either the first or the second spinner) and whether the time is in 12h or 24h format. Both fields have a `locale` property that accepts values in the format specified [here](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html) as Locale ID. For example, using `en_GB` will result in month names spinner in the middle and values between 0 and 23 for the hours, while using `en_US` will result in month names spinner on the left and values between 1 and 12 for the hours. Changing the locale is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L37), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L32) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L34) applications.
- Formats
-Aside from the default formats that are dependent on the value of the `locale` property, you can add your custom format that can include ordering of the date/time values and also custom text. The property controlling the format in the `DatePickerField` is called `dateFormat` and the property controlling the format in the `TimePickerField` is `timeFormat`. Changing the default formats is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L56), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L51) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L53) applications.
+Aside from the default formats that are dependent on the value of the `locale` property, you can add your custom format that can include ordering of the date/time values and also custom text. The property controlling the format in the `DatePickerField` is called `dateFormat` and the property controlling the format in the `TimePickerField` is `timeFormat`. Changing the default formats is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L42), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L37) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L39) applications.
- Minimum and Maximum Dates
@@ -102,7 +115,7 @@ The `DatePickerField` has a `minDate` and `maxDate` properties that allow limiti
- Using 12 h and 24 h Time Formats
-The `TimePickerField` will determine whether to use 12 or 24 hour format (for formatting of the selected time in the field and for the values of the hour spinner) based on the selected region in the settings of the iOS device and based on the Use 24-Hour Format settings of the Android device. To change the default setting on Android, you need to use the `timeFormat` property and to change the setting on iOS, you need to use the `locale` property. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L27), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L22) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L24) applications.
+The `TimePickerField` will determine whether to use 12 or 24 hour format (for formatting of the selected time in the field and for the values of the hour spinner) based on the selected region in the settings of the iOS device and based on the Use 24-Hour Format settings of the Android device. To change the default setting on Android, you need to use the `timeFormat` property and to change the setting on iOS, you need to use the `locale` property. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L66), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L61) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L63) applications.
- CSS
@@ -110,11 +123,50 @@ You can use css to style the `DatePickerField` and the `TimePickerField`. The fi
-Here's the css used to achieve the above result, as used in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.css#L9), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.css#L9) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L164) applications.
+Here's the css used to achieve the above result, as used in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.css#L22), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.css#L22) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L350) applications.
+
+### DateTimePickerFields
+The `DateTimePickerFields` extends `GridLayout` that contains instances of `DatePickerField` and `TimePickerField`, when tapped, they open a picker dialog that allows date/time selection.
+
+- Getting/Setting Date and Time
+
+The `DateTimePickerFields` has a `date` property which can be used to get its current value. You can also set its value through markup. `DateTimePickerFields`' `date` property will just pass the string you provide as a parameter to the [Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L109), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L104) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L106) applications.
+
+- Orientation
+
+The `DateTimePickerFields` have an `orientation` property which allows changing the way the fields are laid out. If the orientation is `horizontal` (the default), the fields are on the same row, if the orienation is `vertical`, the fields will be on separate rows. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L160), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L155) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L157) applications.
+
+- Auto Pick Time
+
+When a date is picked with the date component of the `DateTimePickerFields`, the value of the `date` property is updated with the value that is picked. Since the time component also controls the same property, it may be meaningful to display or not to display this value. The `autoPickTime` property controls whether the time component should display the time of the `date` property as soon as it is assigned (when date is picked). Default is `false`, which means that when the user selects a date, the time component will keep displaying its hint text until time is explicitly selected through the time spinners. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L126), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L121) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L123) applications.
+
+- Picker Texts
+
+When one of the fields is tapped, a popup is opened. The popup has an OK and Cancel buttons and an optional title. Their text values are controlled respectively by the properties `pickerOkText`, `pickerCancelText`, `pickerTitleDate` and `pickerTitleTime`. By default, the texts of the buttons OK and Cancel are `OK` and `Cancel` on iOS, and a localized version of OK and Cancel, dependent on the current setting of the device on Android. The `pickerTitleDate` and `pickerTitleTime` are undefined. Changing these values is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L126), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L121) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L123) applications.
+
+- Localization
+
+By default the `DateTimePickerFields` will use the current language and region settings of the device to determine their locale. The locale is used for the names of the months, for the date picking spinners order (the month selector can be either the first or the second spinner) and whether the time is in 12h or 24h format. Both fields have a `locale` property that accepts values in the format specified [here](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html) as Locale ID. For example, using `en_GB` will result in month names spinner in the middle and values between 0 and 23 for the hours, while using `en_US` will result in month names spinner on the left and values between 1 and 12 for the hours. Changing the locale is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L139), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L134) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L136) applications.
+
+- Formats
+
+Aside from the default formats that are dependent on the value of the `locale` property, you can add your custom format that can include ordering of the date/time values and also custom text. The property controlling the format for the date component is called `dateFormat` and the property controlling the format in the time component is `timeFormat`. Changing the default formats is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L145), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L140) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L142) applications.
+
+- Minimum and Maximum Dates
+
+The `DateTimePickerFields` has a `minDate` and `maxDate` properties that allow limiting the values that can be selected. Note that the values of these properties have effect only on the date component, while the time component can not be limited - it will always allow any hour for any given date. This is demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L113), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L108) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L110) applications.
+
+- Using 12 h and 24 h Time Formats
+
+The time component will determine whether to use 12 or 24 hour format (for formatting of the selected time in the field and for the values of the hour spinner) based on the selected region in the settings of the iOS device and based on the Use 24-Hour Format settings of the Android device. To change the default setting on Android, you need to use the `timeFormat` property and to change the setting on iOS, you need to use the `locale` property. Here's an example in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-page.xml#L118), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.html#L113) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L115) applications.
+
+- CSS
+
+You can use css to style the `DateTimePickerFields`. The element can be styled like any other layout, additionally the `DatePickerField` and the `TimePickerField` that it contains can be styled as explained in their documentation section.
### DateTimePicker
-Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pickDate` and `pickTime` methods which are public, so they can also be manually called in case a more customized picker is desired. The `pickDate` method accepts `DatePickerOptions`, while the `pickTime` method accepts `TimePickerOptions`. These options allow having the same features as in the fields. These methods are demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-view-model.ts#L19), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.ts#L32) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L101) applications.
+Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pickDate` and `pickTime` methods which are public, so they can also be manually called in case a more customized picker is desired. The `pickDate` method accepts `DatePickerOptions`, while the `pickTime` method accepts `TimePickerOptions`. These options allow having the same features as in the fields. These methods are demonstrated in the [demo](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo/app/home/home-view-model.ts#L25), [demo-angular](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-angular/src/app/home/home.component.ts#L44) and [demo-vue](https://github.com/NativeScript/nativescript-datetimepicker/blob/master/demo-vue/app/components/Home.vue#L219) applications.
## API
@@ -122,12 +174,12 @@ Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pick
| Property | Description |
| --- | --- |
-| `date` | The date the picker field is currently displaying. |
-| `minDate` | The minimum date the picker field can select. |
-| `maxDate` | The maximum date the picker field can select. |
-| `locale` | Identifier of a locale that will be used to localize the names of the month names and also the order of the spinners (with `en_UK` first spinner is day, with `en_US` first spinner is month) (default is based on the device’s locale settings). |
+| `date` | The date the picker field is currently displaying. Property is of type `Date`. When used in markup, the provided string will be passed to the [Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) to create a new `Date` object. |
+| `minDate` | The minimum date the picker field can select. Parsing of dates is handled similarly as with `date` property. |
+| `maxDate` | The maximum date the picker field can select. Parsing of dates is handled similarly as with `date` property. |
+| `locale` | Identifier of a locale that will be used to localize the names of the month names and also the order of the spinners (with `en_GB` first spinner is day, with `en_US` first spinner is month) (default is based on the device’s locale settings). |
| `dateFormat` | Format used for the text in the picker field (on android used as a pattern for a [SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat), on iOS used as a dateFormat for [NSDateFormatter](https://developer.apple.com/documentation/foundation/nsdateformatter), default is generated by the current value of the `locale` property). |
-| `pickerDefaultDate` | The date that will be displayed in the picker, if it is opened while date is undefined (if `pickerDefaultDate` is undefined, the picker will display today) |
+| `pickerDefaultDate` | The date that will be displayed in the picker, if it is opened while date is undefined (if `pickerDefaultDate` is undefined, the picker will display today). Parsing of dates is handled similarly as with `date` property. |
| `pickerTitle` | Text that will be displayed as title of the picker, default is undefined. |
| `pickerOkText` | Text for the confirmation button of the picker (default is OK on iOS, localized version of OK on android (based on the devices locale settings)). |
| `pickerCancelText` | Text for the cancel button of the picker (default is Cancel on iOS, localized version of Cancel on android (based on the devices locale settings)). |
@@ -136,14 +188,34 @@ Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pick
| Property | Description |
| --- | --- |
-| `time` | The time the picker field is currently displaying. |
+| `time` | The time the picker field is currently displaying. Property is of type `Date`. When used in markup, the provided string will be parsed to a new `Date` object if it is in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) format. |
| `locale` | Identifier of a locale that will be used to create locale-specific time formatter of the time (if the format is 12-Hour, with de_DE locale “vorm.”/”nachm.” will be used to show whether time is before/after noon, with en_US locale “am”/”pm” will be used) (default is based on the device’s locale settings). The locale will also be used on iOS to determine whether the picker will be in 12 or 24 hour format. |
| `timeFormat` | Format used for the text in the picker field (on android used as a pattern for a [SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat), on iOS used as a dateFormat for [NSDateFormatter](https://developer.apple.com/documentation/foundation/nsdateformatter), default is generated by the current value of the locale property), the format will also be used on Android to determine whether the picker will be in 12 or 24 hour format. |
-| `pickerDefaultTime` | The time that will be displayed in the picker, if it is opened while time is undefined (if defaultTime is undefined, the picker will display now). |
+| `pickerDefaultTime` | The time that will be displayed in the picker, if it is opened while time is undefined (if defaultTime is undefined, the picker will display now). Parsing is handled similarly as with `time` property. |
| `pickerTitle` | Text that will be displayed as title of the picker, default is undefined. |
| `pickerOkText` | Text for the confirmation button of the picker (default is OK on iOS, localized version of OK on android (based on the devices locale settings)). |
| `pickerCancelText` | Text for the cancel button of the picker (default is Cancel on iOS, localized version of Cancel on android (based on the devices locale settings)). |
+### DateTimePickerFields API
+
+| Property | Description |
+| --- | --- |
+| `date` | The date the picker fields are currently displaying. Property is of type `Date`. When used in markup, the provided string will be passed to the [Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) to create a new `Date` object. |
+| `minDate` | The minimum date the date component can select. Parsing of dates is handled similarly as with `date` property. |
+| `maxDate` | The maximum date the time component can select. Parsing of dates is handled similarly as with `date` property. |
+| `locale` | Identifier of a locale that will be used to localize the names of the month names, the order of the date spinners (with `en_GB` first spinner is day, with `en_US` first spinner is month), and to create locale-specific time formatter of the time (if the format is 12-Hour, with de_DE locale “vorm.”/”nachm.” will be used to show whether time is before/after noon, with en_US locale “am”/”pm” will be used) (default is based on the device’s locale settings). The locale will also be used on iOS to determine whether the picker will be in 12 or 24 hour format. |
+| `dateFormat` | Format used for the text in the picker field (on android used as a pattern for a [SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat), on iOS used as a dateFormat for [NSDateFormatter](https://developer.apple.com/documentation/foundation/nsdateformatter), default is generated by the current value of the `locale` property). |
+| `timeFormat` | Format used for the text in the picker field (on android used as a pattern for a [SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat), on iOS used as a dateFormat for [NSDateFormatter](https://developer.apple.com/documentation/foundation/nsdateformatter), default is generated by the current value of the locale property), the format will also be used on Android to determine whether the picker will be in 12 or 24 hour format. |
+| `pickerDefaultDate` | The date and time that will be displayed in the pickers, if opened while `date` is `undefined` (if `pickerDefaultDate` is undefined, the picker will display now). Parsing of dates is handled similarly as with `date` property. |
+| `pickerTitleDate` | Text that will be displayed as title of the picker, when the date component is tapped, default is undefined. |
+| `pickerTitleTime` | Text that will be displayed as title of the picker, when the time component is tapped, default is undefined. |
+| `pickerOkText` | Text for the confirmation button of the picker (default is OK on iOS, localized version of OK on android (based on the devices locale settings)). |
+| `pickerCancelText` | Text for the cancel button of the picker (default is Cancel on iOS, localized version of Cancel on android (based on the devices locale settings)). |
+| `autoPickTime` | Value that indicates whether the time component should be assigned a value as soon as a date is picked by the date component, default is false. |
+| `orientation` | Value that indicates how the date and time components will be arranged, default is "horizontal", which means that they will be on the same row. |
+| `hintDate` | Text displayed in the date component when `date` is `null`. |
+| `hintTime` | Text displayed in the time component when `date` is `null`. |
+
### DateTimePicker API
**DateTimePicker**:
@@ -161,7 +233,7 @@ Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pick
| `date` | The date that will be displayed in the picker, (if not provided, the picker will display today). |
| `minDate` | The minimum date that can be selected. |
| `maxDate` | The maximum date that can be selected. |
-| `locale` | Identifier of a locale that will be used to localize the names of the month names and also the order of the spinners (with `en_UK` first spinner is day, with `en_US` first spinner is month, default is based on the device’s locale settings). |
+| `locale` | Identifier of a locale that will be used to localize the names of the month names and also the order of the spinners (with `en_GB` first spinner is day, with `en_US` first spinner is month, default is based on the device’s locale settings). |
| `title` | Text that will be displayed as title of the picker, default is undefined. |
| `okButtonText` | Text for the confirmation button of the picker (default is OK on iOS, localized version of OK on android (based on the devices locale settings)). |
| `cancelButtonText` | Text for the cancel button of the picker (default is Cancel on iOS, localized version of Cancel on android (based on the devices locale settings)). |
diff --git a/demo-angular/.npmrc b/demo-angular/.npmrc
new file mode 100644
index 0000000..9cf9495
--- /dev/null
+++ b/demo-angular/.npmrc
@@ -0,0 +1 @@
+package-lock=false
\ No newline at end of file
diff --git a/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png b/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png
deleted file mode 100644
index eec1d1e..0000000
Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png and /dev/null differ
diff --git a/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png b/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png
deleted file mode 100644
index eaebbec..0000000
Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png and /dev/null differ
diff --git a/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png b/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png
deleted file mode 100644
index 3a5c87f..0000000
Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png and /dev/null differ
diff --git a/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png b/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png
deleted file mode 100644
index 8eba30d..0000000
Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png and /dev/null differ
diff --git a/demo-angular/nsconfig.json b/demo-angular/nsconfig.json
index a64c9fa..b38346b 100644
--- a/demo-angular/nsconfig.json
+++ b/demo-angular/nsconfig.json
@@ -1,4 +1,4 @@
{
"appResourcesPath": "App_Resources",
"appPath": "src"
-}
+}
\ No newline at end of file
diff --git a/demo-angular/package.json b/demo-angular/package.json
index fa43c29..821ee23 100644
--- a/demo-angular/package.json
+++ b/demo-angular/package.json
@@ -1,55 +1,46 @@
{
- "nativescript": {
- "id": "org.nativescript.datetimepicker.demong",
- "tns-android": {
- "version": "5.3.0"
- },
- "tns-ios": {
- "version": "5.3.0"
- }
+ "nativescript": {
+ "id": "org.nativescript.datetimepicker.demong",
+ "tns-android": {
+ "version": "6.2.0"
},
- "description": "NativeScript DateTimePicker Demo NG",
- "license": "SEE LICENSE IN LICENSE FILE",
- "repository": "https://github.com/NativeScript/nativescript-datetimepicker",
- "scripts": {
- "ci.tslint": "npm i && tslint --config '../tslint.json' 'src/**/*.ts'",
- "build.plugin": "cd ../src && npm run build",
- "e2e": "node ./node_modules/nativescript-dev-appium/check-dev-deps.js && tsc -p e2e && mocha --opts ./e2e/config/mocha.opts ",
- "e2e-watch": "tsc -p e2e --watch"
- },
- "dependencies": {
- "@angular/animations": "~7.2.0",
- "@angular/common": "~7.2.0",
- "@angular/compiler": "~7.2.0",
- "@angular/core": "~7.2.0",
- "@angular/forms": "~7.2.0",
- "@angular/http": "~7.2.0",
- "@angular/platform-browser": "~7.2.0",
- "@angular/platform-browser-dynamic": "~7.2.0",
- "@angular/router": "~7.2.0",
- "nativescript-angular": "~7.2.0",
- "nativescript-datetimepicker": "file:../src",
- "nativescript-theme-core": "~1.0.4",
- "reflect-metadata": "~0.1.10",
- "rxjs": "~6.4.0",
- "tns-core-modules": "^5.0.0",
- "zone.js": "~0.8.18"
- },
- "devDependencies": {
- "@nativescript/schematics": "~0.5.0",
- "nativescript-dev-typescript": "~0.9.0",
- "nativescript-dev-webpack": "~0.21.0",
- "@angular/compiler-cli": "~7.2.0",
- "@ngtools/webpack": "~7.2.0",
- "@types/chai": "~4.1.7",
- "@types/mocha": "~5.2.5",
- "@types/node": "~10.12.18",
- "mocha": "~5.2.0",
- "mocha-junit-reporter": "~1.18.0",
- "mocha-multi": "~1.0.1",
- "mochawesome": "~3.1.1",
- "nativescript-dev-appium": "~5.0.0",
- "tslint": "~5.11.0"
- },
- "readme": "NativeScript DateTimePicker Demo NG"
+ "tns-ios": {
+ "version": "6.2.0"
+ }
+ },
+ "description": "NativeScript DateTimePicker Demo NG",
+ "license": "SEE LICENSE IN LICENSE FILE",
+ "repository": "https://github.com/NativeScript/nativescript-datetimepicker",
+ "scripts": {
+ "ci.tslint": "npm i && tslint --config '../tslint.json' 'src/**/*.ts'",
+ "build.plugin": "cd ../src && npm run build",
+ "e2e": "node ./node_modules/nativescript-dev-appium/check-dev-deps.js && tsc -p e2e && mocha --opts ./e2e/config/mocha.opts ",
+ "e2e-watch": "tsc -p e2e --watch"
+ },
+ "dependencies": {
+ "@angular/animations": "~8.2.0",
+ "@angular/common": "~8.2.0",
+ "@angular/compiler": "~8.2.0",
+ "@angular/core": "~8.2.0",
+ "@angular/forms": "~8.2.0",
+ "@angular/platform-browser": "~8.2.0",
+ "@angular/platform-browser-dynamic": "~8.2.0",
+ "@angular/router": "~8.2.0",
+ "nativescript-angular": "~8.20.0",
+ "nativescript-datetimepicker": "file:../src",
+ "nativescript-theme-core": "~1.0.4",
+ "reflect-metadata": "~0.1.10",
+ "rxjs": "^6.4.0",
+ "tns-core-modules": "^6.0.0",
+ "zone.js": "^0.9.1"
+ },
+ "devDependencies": {
+ "@angular/compiler-cli": "~8.2.0",
+ "@ngtools/webpack": "~8.2.0",
+ "@types/node": "~10.12.18",
+ "nativescript-dev-webpack": "^1.3.0",
+ "tslint": "~5.11.0",
+ "typescript": "~3.5.3"
+ },
+ "readme": "NativeScript DateTimePicker Demo NG"
}
diff --git a/demo-angular/src/app/home/home.component.css b/demo-angular/src/app/home/home.component.css
index 2483bd2..c33ffc6 100644
--- a/demo-angular/src/app/home/home.component.css
+++ b/demo-angular/src/app/home/home.component.css
@@ -6,6 +6,15 @@
color: #303F9F;
}
+.header {
+ font-size: 16;
+ margin-top: 12;
+ margin-bottom: 6;
+ color: white;
+ background-color: #2196F3;
+ text-align: center;
+}
+
label {
padding: 6 4;
}
diff --git a/demo-angular/src/app/home/home.component.html b/demo-angular/src/app/home/home.component.html
index a2f8da3..5bd5be4 100644
--- a/demo-angular/src/app/home/home.component.html
+++ b/demo-angular/src/app/home/home.component.html
@@ -2,69 +2,167 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo-angular/src/app/home/home.component.ts b/demo-angular/src/app/home/home.component.ts
index 60b464f..8f4e9e2 100644
--- a/demo-angular/src/app/home/home.component.ts
+++ b/demo-angular/src/app/home/home.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from "@angular/core";
+import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
import { DateTimePicker } from "nativescript-datetimepicker";
import { EventData } from "tns-core-modules/data/observable";
import { Button } from "tns-core-modules/ui/button";
@@ -10,19 +10,31 @@ import { Button } from "tns-core-modules/ui/button";
styleUrls: ['home.component.css']
})
export class HomeComponent implements OnInit {
- private _dateText: string;
- private _timeText: string;
- private _dateTime: Date;
+ public dateText: string = "tap to select date";
+ public timeText: string = "tap to select time";
+ public dateTimeText: string = "tap to select date and time";
+ public dateTime1: Date = new Date();
+ public dateTime2: Date = new Date();
+ public dateTime3: Date = new Date();
+ public dateOpacity: number;
+ public timeOpacity: number;
+ public dateTimeOpacity: number;
+ public customOpacity: number;
+ public dateVisibility: string;
+ public timeVisibility: string;
+ public dateTimeVisibility: string;
+ public customVisibility: string;
+ private _expandedId: string;
+
+ @ViewChild("scrollView", { static: false }) scrollView: ElementRef;
constructor() {
// Use the component constructor to inject providers.
+ this.expandCollapse(null);
}
ngOnInit(): void {
// Init your component properties here.
- this._dateText = "tap to select date";
- this._timeText = "tap to select time";
- this._dateTime = new Date();
}
onPickDateTap(args: EventData): void {
@@ -37,14 +49,10 @@ export class HomeComponent implements OnInit {
okButtonText: "OK",
cancelButtonText: "Cancel",
title: "choose date",
- locale: "en_UK"
- }).then((selected: Date) => {
- if (selected) {
- const d = selected.getDate();
- const m = selected.getMonth() + 1;
- const y = selected.getFullYear();
- const dateText = (d < 10 ? '0' : '') + d + '.' + (m < 10 ? '0' : '') + m + '.' + y;
- this._dateText = dateText;
+ locale: "en_GB"
+ }).then((selectedDate: Date) => {
+ if (selectedDate) {
+ this.dateText = this.getFormattedDate(selectedDate);
}
});
}
@@ -60,31 +68,75 @@ export class HomeComponent implements OnInit {
okButtonText: "OK",
cancelButtonText: "Cancel",
title: "choose time",
- locale: "en_UK",
+ locale: "en_GB",
is24Hours: true
- }).then((selected: Date) => {
- if (selected) {
- const h = selected.getHours();
- const m = selected.getMinutes();
- const timeText = (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m;
- this._timeText = timeText;
+ }).then((selectedTime: Date) => {
+ if (selectedTime) {
+ this.timeText = this.getFormattedTime(selectedTime);
}
});
}
- get dateText() {
- return this._dateText;
+ onPickDateTimeTap(args: EventData): void {
+ const dateToday = new Date();
+ DateTimePicker.pickDate({
+ context: (
@@ -87,12 +184,30 @@
return {
dateText: "tap to select date",
timeText: "tap to select time",
- dateTime: new Date()
+ dateTimeText: "tap to select date and time",
+ dateTime1: new Date(),
+ dateTime2: new Date(),
+ dateTime3: new Date(),
+ dateOpacity: 1,
+ timeOpacity: 1,
+ dateTimeOpacity: 1,
+ customOpacity: 1,
+ dateVisibility: 'collapse',
+ timeVisibility: 'collapse',
+ dateTimeVisibility: 'collapse',
+ customVisibility: 'collapse',
+ _expandedId: null
}
},
methods: {
- onDateTimeChange: function(args) {
- this.dateTime = args.value;
+ onDateTimeChange1: function(args) {
+ this.dateTime1 = args.value;
+ },
+ onDateTimeChange2: function(args) {
+ this.dateTime2 = args.value;
+ },
+ onDateTimeChange3: function(args) {
+ this.dateTime3 = args.value;
},
onPickDateTap: function(args) {
const dateToday = new Date();
@@ -107,15 +222,11 @@
okButtonText: "OK",
cancelButtonText: "Cancel",
title: "choose date",
- locale: "en_UK"
+ locale: "en_GB"
})
- .then(selected => {
- if (selected) {
- const d = selected.getDate();
- const m = selected.getMonth() + 1;
- const y = selected.getFullYear();
- const dateText = (d < 10 ? '0' : '') + d + '.' + (m < 10 ? '0' : '') + m + '.' + y;
- this.dateText = dateText;
+ .then(selectedDate => {
+ if (selectedDate) {
+ this.dateText = this.getFormattedDate(selectedDate);
}
});
},
@@ -131,17 +242,76 @@
okButtonText: "OK",
cancelButtonText: "Cancel",
title: "choose time",
- locale: "en_UK",
+ locale: "en_GB",
is24Hours: true
})
- .then(selected => {
- if (selected) {
- const h = selected.getHours();
- const m = selected.getMinutes();
- const timeText = (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m;
- this.timeText = timeText;
+ .then(selectedTime => {
+ if (selectedTime) {
+ this.timeText = this.getFormattedTime(selectedTime);
+ }
+ });
+ },
+ onPickDateTimeTap: function(args) {
+ const dateToday = new Date();
+ DateTimePicker
+ .pickDate({
+ context: args.object._context,
+ date: dateToday,
+ title: "choose date",
+ locale: "en_GB"
+ })
+ .then(selectedDate => {
+ if (selectedDate) {
+ DateTimePicker
+ .pickTime({
+ context: args.object._context,
+ time: selectedDate,
+ title: "choose time",
+ locale: "en_GB"
+ })
+ .then(selectedDateTime => {
+ if (selectedDateTime) {
+ this.dateTimeText = this.getFormattedDate(selectedDateTime) + ' ' + this.getFormattedTime(selectedDateTime);
+ }
+ });
}
});
+ },
+ onHeaderTap: function(args) {
+ const buttonId = args.object.id;
+ const isCurrentlyExpanded = buttonId === this._expandedId;
+ if (isCurrentlyExpanded) {
+ this.expandCollapse(null);
+ } else {
+ this.expandCollapse(buttonId);
+ }
+ this.$refs.scrollView.nativeView.scrollToVerticalOffset(0, false);
+ },
+ expandCollapse: function(expandId) {
+ this.dateOpacity = expandId === 'date' ? 0.7 : 1;
+ this.dateVisibility = expandId === 'date' ? 'visible' : 'collapse';
+
+ this.timeOpacity = expandId === 'time' ? 0.7 : 1;
+ this.timeVisibility = expandId === 'time' ? 'visible' : 'collapse';
+
+ this.dateTimeOpacity = expandId === 'dateTime' ? 0.7 : 1;
+ this.dateTimeVisibility = expandId === 'dateTime' ? 'visible' : 'collapse';
+
+ this.customOpacity = expandId === 'custom' ? 0.7 : 1;
+ this.customVisibility = expandId === 'custom' ? 'visible' : 'collapse';
+
+ this._expandedId = expandId;
+ },
+ getFormattedDate: function(date) {
+ const d = date.getDate();
+ const m = date.getMonth() + 1;
+ const y = date.getFullYear();
+ return (d < 10 ? '0' : '') + d + '.' + (m < 10 ? '0' : '') + m + '.' + y;
+ },
+ getFormattedTime: function(date) {
+ const h = date.getHours();
+ const m = date.getMinutes();
+ return (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m;
}
}
};
@@ -161,6 +331,15 @@
color: #303F9F;
}
+ .header {
+ font-size: 16;
+ margin-top: 12;
+ margin-bottom: 6;
+ color: white;
+ background-color: #2196F3;
+ text-align: center;
+ }
+
label {
padding: 6 4;
}
diff --git a/demo-vue/package.json b/demo-vue/package.json
index d5c2468..3a0fe44 100644
--- a/demo-vue/package.json
+++ b/demo-vue/package.json
@@ -2,10 +2,10 @@
"nativescript": {
"id": "org.nativescript.datetimepicker.demovue",
"tns-android": {
- "version": "5.3.0"
+ "version": "6.2.0"
},
"tns-ios": {
- "version": "5.3.0"
+ "version": "6.2.0"
}
},
"description": "NativeScript DateTimePicker Demo Vue",
@@ -14,18 +14,18 @@
"dependencies": {
"nativescript-datetimepicker": "file:../src",
"nativescript-theme-core": "~1.0.4",
- "nativescript-vue": "~2.0.0",
- "tns-core-modules": "^5.0.0"
+ "nativescript-vue": "~2.4.0",
+ "tns-core-modules": "^6.0.0"
},
"devDependencies": {
"@babel/core": "~7.2.0",
"@babel/preset-env": "~7.2.0",
"babel-loader": "~8.0.0",
- "nativescript-dev-typescript": "~0.9.0",
- "nativescript-dev-webpack": "~0.21.0",
- "nativescript-vue-template-compiler": "~2.0.2",
- "node-sass": "~4.9.0",
- "vue-loader": "~15.4.0"
+ "nativescript-dev-webpack": "^1.3.0",
+ "nativescript-vue-template-compiler": "~2.4.0",
+ "node-sass": "~4.12.0",
+ "vue-loader": "~15.4.0",
+ "typescript": "~3.5.3"
},
"readme": "NativeScript DateTimePicker Demo Vue"
}
diff --git a/demo/.npmrc b/demo/.npmrc
new file mode 100644
index 0000000..9cf9495
--- /dev/null
+++ b/demo/.npmrc
@@ -0,0 +1 @@
+package-lock=false
\ No newline at end of file
diff --git a/demo/app/home/home-page.css b/demo/app/home/home-page.css
index 1df44eb..aee7c01 100644
--- a/demo/app/home/home-page.css
+++ b/demo/app/home/home-page.css
@@ -6,6 +6,15 @@
color: #303F9F;
}
+.header {
+ font-size: 16;
+ margin-top: 12;
+ margin-bottom: 6;
+ color: white;
+ background-color: #2196F3;
+ text-align: center;
+}
+
label {
padding: 6 4;
}
diff --git a/demo/app/home/home-page.xml b/demo/app/home/home-page.xml
index 9ec3c43..31ef9d9 100644
--- a/demo/app/home/home-page.xml
+++ b/demo/app/home/home-page.xml
@@ -7,70 +7,167 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/app/home/home-view-model.ts b/demo/app/home/home-view-model.ts
index e30cb86..a1ee075 100644
--- a/demo/app/home/home-view-model.ts
+++ b/demo/app/home/home-view-model.ts
@@ -2,14 +2,20 @@ import { Observable } from "tns-core-modules/data/observable";
import { DateTimePicker } from "nativescript-datetimepicker";
import { EventData } from "tns-core-modules/data/observable";
import { Button } from "tns-core-modules/ui/button";
+import { ScrollView } from "tns-core-modules/ui/scroll-view";
export class HomeViewModel extends Observable {
+ private scrollView: ScrollView;
constructor() {
super();
this.set('dateText', "tap to select date");
this.set('timeText', "tap to select time");
- this.set('dateTime', new Date());
+ this.set('dateTimeText', "tap to select date and time");
+ this.set('dateTime1', new Date());
+ this.set('dateTime2', new Date());
+ this.set('dateTime3', new Date());
+ this.expandCollapse(null);
}
onPickDateTap(args: EventData): void {
@@ -24,14 +30,10 @@ export class HomeViewModel extends Observable {
okButtonText: "OK",
cancelButtonText: "Cancel",
title: "choose date",
- locale: "en_UK"
- }).then((selected: Date) => {
- if (selected) {
- const d = selected.getDate();
- const m = selected.getMonth() + 1;
- const y = selected.getFullYear();
- const dateText = (d < 10 ? '0' : '') + d + '.' + (m < 10 ? '0' : '') + m + '.' + y;
- this.set('dateText', dateText);
+ locale: "en_GB"
+ }).then((selectedDate: Date) => {
+ if (selectedDate) {
+ this.set('dateText', this.getFormattedDate(selectedDate));
}
});
}
@@ -47,15 +49,77 @@ export class HomeViewModel extends Observable {
okButtonText: "OK",
cancelButtonText: "Cancel",
title: "choose time",
- locale: "en_UK",
+ locale: "en_GB",
is24Hours: true
- }).then((selected: Date) => {
- if (selected) {
- const h = selected.getHours();
- const m = selected.getMinutes();
- const timeText = (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m;
- this.set('timeText', timeText);
+ }).then((selectedTime: Date) => {
+ if (selectedTime) {
+ this.set('timeText', this.getFormattedTime(selectedTime));
}
});
}
+
+ onPickDateTimeTap(args: EventData): void {
+ const dateToday = new Date();
+ DateTimePicker.pickDate({
+ context: (args.object)._context,
+ date: dateToday,
+ title: "choose date",
+ locale: "en_GB",
+ }).then((selectedDate: Date) => {
+ if (selectedDate) {
+ DateTimePicker.pickTime({
+ context: (args.object)._context,
+ time: selectedDate,
+ title: "choose time",
+ locale: "en_GB",
+ }).then((selectedDateTime: Date) => {
+ if (selectedDateTime) {
+ this.set('dateTimeText', this.getFormattedDate(selectedDateTime) + ' ' + this.getFormattedTime(selectedDateTime));
+ }
+ });
+ }
+ });
+ }
+
+ scrollViewLoaded(args: EventData): void {
+ this.scrollView = args.object;
+ }
+
+ onHeaderTap(args: EventData): void {
+ const buttonId = (args.object).id;
+ const isCurrentlyExpanded = this.get(buttonId + "Visibility") === 'visible';
+ if (isCurrentlyExpanded) {
+ this.expandCollapse(null);
+ } else {
+ this.expandCollapse(buttonId);
+ }
+ this.scrollView.scrollToVerticalOffset(0, false);
+ }
+
+ expandCollapse(expandId: string): void {
+ this.set('dateOpacity', expandId === 'date' ? 0.7 : 1);
+ this.set('dateVisibility', expandId === 'date' ? 'visible' : 'collapse');
+
+ this.set('timeOpacity', expandId === 'time' ? 0.7 : 1);
+ this.set('timeVisibility', expandId === 'time' ? 'visible' : 'collapse');
+
+ this.set('dateTimeOpacity', expandId === 'dateTime' ? 0.7 : 1);
+ this.set('dateTimeVisibility', expandId === 'dateTime' ? 'visible' : 'collapse');
+
+ this.set('customOpacity', expandId === 'custom' ? 0.7 : 1);
+ this.set('customVisibility', expandId === 'custom' ? 'visible' : 'collapse');
+ }
+
+ getFormattedDate(date: Date): string {
+ const d = date.getDate();
+ const m = date.getMonth() + 1;
+ const y = date.getFullYear();
+ return (d < 10 ? '0' : '') + d + '.' + (m < 10 ? '0' : '') + m + '.' + y;
+ }
+
+ getFormattedTime(date: Date): string {
+ const h = date.getHours();
+ const m = date.getMinutes();
+ return (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m;
+ }
}
diff --git a/demo/package.json b/demo/package.json
index 57a03a8..f5800a7 100644
--- a/demo/package.json
+++ b/demo/package.json
@@ -2,10 +2,10 @@
"nativescript": {
"id": "org.nativescript.datetimepicker.demo",
"tns-android": {
- "version": "5.3.0"
+ "version": "6.2.0"
},
"tns-ios": {
- "version": "5.3.0"
+ "version": "6.2.0"
}
},
"description": "NativeScript DateTimePicker Demo Core",
@@ -18,12 +18,12 @@
"dependencies": {
"nativescript-datetimepicker": "file:../src",
"nativescript-theme-core": "~1.0.4",
- "tns-core-modules": "^5.0.0"
+ "tns-core-modules": "^6.0.0"
},
"devDependencies": {
- "nativescript-dev-typescript": "~0.9.0",
- "nativescript-dev-webpack": "~0.21.0",
- "tslint": "~5.11.0"
+ "nativescript-dev-webpack": "^1.3.0",
+ "tslint": "~5.11.0",
+ "typescript": "~3.5.3"
},
"readme": "NativeScript DateTimePicker Demo Core"
}
diff --git a/src/angular/nativescript-datetimepicker.accessors.ts b/src/angular/nativescript-datetimepicker.accessors.ts
index 20a8d03..ae23f41 100644
--- a/src/angular/nativescript-datetimepicker.accessors.ts
+++ b/src/angular/nativescript-datetimepicker.accessors.ts
@@ -3,6 +3,7 @@ import { NG_VALUE_ACCESSOR } from "@angular/forms";
import { BaseValueAccessor } from "nativescript-angular/forms/value-accessors";
import { DatePickerField } from "../ui/date-picker-field";
import { TimePickerField } from "../ui/time-picker-field";
+import { DateTimePickerFields } from "../ui/date-time-picker-fields";
const DATE_PICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
@@ -16,6 +17,12 @@ const TIME_PICKER_VALUE_ACCESSOR = {
multi: true,
};
+const DATE_TIME_PICKERS_VALUE_ACCESSOR = {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => DateTimePickersValueAccessor),
+ multi: true,
+};
+
/**
* The accessor for setting a date and listening to changes that is used by the
* {@link NgModel} directives.
@@ -32,10 +39,13 @@ const TIME_PICKER_VALUE_ACCESSOR = {
"date-picker-field[ngModel],date-picker-field[formControlName],date-picker-field[formControl]",
providers: [DATE_PICKER_VALUE_ACCESSOR],
host: {
- "(dateChange)": "onChange($event.value)",
+ "(dateChange)": "handleDateChange($event)",
+ "(datePickerOpened)": "handleDatePickerOpened($event)",
+ "(datePickerClosed)": "handleDatePickerClosed($event)"
},
})
export class DatePickerValueAccessor extends BaseValueAccessor {
+ private _hasBeenOpened = false;
constructor(elementRef: ElementRef) {
super(elementRef.nativeElement);
}
@@ -44,6 +54,20 @@ export class DatePickerValueAccessor extends BaseValueAccessor
const normalized = super.normalizeValue(value);
this.view.date = normalized;
}
+
+ handleDateChange(args: any) {
+ if (this._hasBeenOpened) {
+ this.onChange(args.value);
+ }
+ }
+
+ handleDatePickerOpened(args: any) {
+ this._hasBeenOpened = true;
+ }
+
+ handleDatePickerClosed(args: any) {
+ this.onTouched();
+ }
}
/**
@@ -62,10 +86,13 @@ export class DatePickerValueAccessor extends BaseValueAccessor
"time-picker-field[ngModel],time-picker-field[formControlName],time-picker-field[formControl]",
providers: [TIME_PICKER_VALUE_ACCESSOR],
host: {
- "(timeChange)": "onChange($event.value)",
+ "(timeChange)": "handleTimeChange($event)",
+ "(timePickerOpened)": "handleTimePickerOpened($event)",
+ "(timePickerClosed)": "handleTimePickerClosed($event)"
},
})
export class TimePickerValueAccessor extends BaseValueAccessor {
+ private _hasBeenOpened = false;
constructor(elementRef: ElementRef) {
super(elementRef.nativeElement);
}
@@ -74,4 +101,67 @@ export class TimePickerValueAccessor extends BaseValueAccessor
const normalized = super.normalizeValue(value);
this.view.time = normalized;
}
+
+ handleTimeChange(args: any) {
+ if (this._hasBeenOpened) {
+ this.onChange(args.value);
+ }
+ }
+
+ handleTimePickerOpened(args: any) {
+ this._hasBeenOpened = true;
+ }
+
+ handleTimePickerClosed(args: any) {
+ this.onTouched();
+ }
+}
+
+/**
+ * The accessor for setting a date and listening to changes that is used by the
+ * {@link NgModel} directives.
+ *
+ * ### Example
+ * ```
+ *
+ * ```
+ */
+@Directive({
+ selector: "DateTimePickerFields[ngModel],DateTimePickerFields[formControlName],DateTimePickerFields[formControl]," +
+ "datetimepickerfields[ngModel],datetimepickerfields[formControlName],datetimepickerfields[formControl]," +
+ "dateTimePickerFields[ngModel],dateTimePickerFields[formControlName],dateTimePickerFields[formControl]," +
+ "date-time-picker-fields[ngModel],date-time-picker-fields[formControlName],date-time-picker-fields[formControl]",
+ providers: [DATE_TIME_PICKERS_VALUE_ACCESSOR],
+ host: {
+ "(dateChange)": "handleDateChange($event)",
+ "(datePickerOpened)": "handlePickerOpened($event)",
+ "(datePickerClosed)": "handlePickerClosed($event)",
+ "(timePickerOpened)": "handlePickerOpened($event)",
+ "(timePickerClosed)": "handlePickerClosed($event)"
+ },
+})
+export class DateTimePickersValueAccessor extends BaseValueAccessor {
+ private _hasBeenOpened = false;
+ constructor(elementRef: ElementRef) {
+ super(elementRef.nativeElement);
+ }
+
+ writeValue(value: any): void {
+ const normalized = super.normalizeValue(value);
+ this.view.date = normalized;
+ }
+
+ handleDateChange(args: any) {
+ if (this._hasBeenOpened) {
+ this.onChange(args.value);
+ }
+ }
+
+ handlePickerOpened(args: any) {
+ this._hasBeenOpened = true;
+ }
+
+ handlePickerClosed(args: any) {
+ this.onTouched();
+ }
}
\ No newline at end of file
diff --git a/src/angular/nativescript-datetimepicker.directives.ts b/src/angular/nativescript-datetimepicker.directives.ts
index a57883b..5c8bb4f 100644
--- a/src/angular/nativescript-datetimepicker.directives.ts
+++ b/src/angular/nativescript-datetimepicker.directives.ts
@@ -1,5 +1,7 @@
import { Directive } from "@angular/core";
-import { DatePickerValueAccessor, TimePickerValueAccessor } from "./nativescript-datetimepicker.accessors";
+import {
+ DatePickerValueAccessor, TimePickerValueAccessor, DateTimePickersValueAccessor
+} from "./nativescript-datetimepicker.accessors";
@Directive({
selector: "DatePickerField"
@@ -11,5 +13,10 @@ export class DatePickerFieldDirective { }
})
export class TimePickerFieldDirective { }
-export const DIRECTIVES = [DatePickerFieldDirective, TimePickerFieldDirective,
- DatePickerValueAccessor, TimePickerValueAccessor];
\ No newline at end of file
+@Directive({
+ selector: "DateTimePickerFields"
+})
+export class DateTimePickerFieldsDirective { }
+
+export const DIRECTIVES = [DatePickerFieldDirective, TimePickerFieldDirective, DateTimePickerFieldsDirective,
+ DatePickerValueAccessor, TimePickerValueAccessor, DateTimePickersValueAccessor];
\ No newline at end of file
diff --git a/src/angular/nativescript-datetimepicker.module.ts b/src/angular/nativescript-datetimepicker.module.ts
index 2a9785b..3dfad8c 100644
--- a/src/angular/nativescript-datetimepicker.module.ts
+++ b/src/angular/nativescript-datetimepicker.module.ts
@@ -2,6 +2,7 @@ import { NgModule } from "@angular/core";
import { registerElement } from "nativescript-angular/element-registry";
import { DatePickerField } from "../ui/date-picker-field";
import { TimePickerField } from "../ui/time-picker-field";
+import { DateTimePickerFields } from "../ui/date-time-picker-fields";
import { DIRECTIVES } from "./nativescript-datetimepicker.directives";
@@ -12,4 +13,5 @@ import { DIRECTIVES } from "./nativescript-datetimepicker.directives";
export class NativeScriptDateTimePickerModule { }
registerElement("DatePickerField", () => DatePickerField);
-registerElement("TimePickerField", () => TimePickerField);
\ No newline at end of file
+registerElement("TimePickerField", () => TimePickerField);
+registerElement("DateTimePickerFields", () => DateTimePickerFields);
\ No newline at end of file
diff --git a/src/datetimepicker.android.ts b/src/datetimepicker.android.ts
index 54616a3..7163c31 100644
--- a/src/datetimepicker.android.ts
+++ b/src/datetimepicker.android.ts
@@ -1,41 +1,34 @@
import { Color } from "tns-core-modules/color";
import { LocalizationUtils } from "./utils/localization-utils";
+import { getDateNow, getDateToday } from "./utils/date-utils";
import {
- DateTimePickerBase, DateTimePickerStyleBase, getDateNow, getDateToday,
+ DateTimePickerBase, DateTimePickerStyleBase,
DatePickerOptions, TimePickerOptions, PickerOptions
} from "./datetimepicker.common";
-interface DialogClickListener {
- new(datePicker: any, dateTime: Date, callback: Function): android.content.DialogInterface.OnClickListener;
-}
-
-interface DialogDismissListener {
- new(callback: Function): android.content.DialogInterface.OnDismissListener;
-}
-
-let DialogClickListener: DialogClickListener;
-let DialogDismissListener: DialogDismissListener;
+let DialogListener: any;
let AppCompatNamespace: any;
-declare let androidx: any;
+declare let global: any;
function initializeAppCompatNamespace(): void {
if (AppCompatNamespace) {
return;
}
- if (androidx && androidx.appcompat) {
- AppCompatNamespace = androidx.appcompat;
+ if (global.androidx && global.androidx.appcompat) {
+ AppCompatNamespace = global.androidx.appcompat;
} else {
AppCompatNamespace = (android.support).v7;
}
}
-function initializeDialogClickListener(): void {
- if (DialogClickListener) {
+function initializeDialogListener(): void {
+ if (DialogListener) {
return;
}
- @Interfaces([android.content.DialogInterface.OnClickListener])
- class DialogClickListenerImpl extends java.lang.Object implements android.content.DialogInterface.OnClickListener {
+ @Interfaces([android.content.DialogInterface.OnClickListener, android.content.DialogInterface.OnDismissListener])
+ class DialogListenerImpl extends java.lang.Object implements android.content.DialogInterface.OnClickListener, android.content.DialogInterface.OnDismissListener {
+ private _isClicked = false;
constructor(public nativePicker: any, public dateTime: Date, public callback: Function) {
super();
return global.__native(this);
@@ -45,6 +38,7 @@ function initializeDialogClickListener(): void {
const callback = this.callback;
const dateTime = this.dateTime;
const nativePicker = this.nativePicker;
+ this._isClicked = true;
switch (which) {
case android.content.DialogInterface.BUTTON_POSITIVE: {
if (nativePicker instanceof android.widget.DatePicker) {
@@ -62,30 +56,19 @@ function initializeDialogClickListener(): void {
}
callback(null);
}
- }
-
- DialogClickListener = DialogClickListenerImpl;
-}
-
-function initializeDialogDismissListener(): void {
- if (DialogDismissListener) {
- return;
- }
-
- @Interfaces([android.content.DialogInterface.OnDismissListener])
- class DialogDismissListenerImpl extends java.lang.Object implements android.content.DialogInterface.OnDismissListener {
- constructor(public callback: Function) {
- super();
- return global.__native(this);
- }
onDismiss(dialog: android.content.DialogInterface) {
+ if (this._isClicked) {
+ // The Picker is dismissed due to a button click,
+ // so the callback is already called.
+ return;
+ }
const callback = this.callback;
callback(null);
}
}
- DialogDismissListener = DialogDismissListenerImpl;
+ DialogListener = DialogListenerImpl;
}
export class DateTimePickerStyle extends DateTimePickerStyleBase {
@@ -166,28 +149,31 @@ export class DateTimePicker extends DateTimePickerBase {
}
static _createNativeDialog(nativePicker: android.view.View, options: PickerOptions, value: Date, callback: Function): android.app.AlertDialog.Builder {
- initializeDialogClickListener();
- initializeDialogDismissListener();
+ initializeDialogListener();
initializeAppCompatNamespace();
DateTimePicker._initializeTextResources(options.context);
const context = options.context;
let dateTime: Date;
if (value) {
+ if (nativePicker instanceof android.widget.DatePicker) {
+ const minDate = (options).minDate;
+ const maxDate = (options).maxDate;
+ value = DateTimePicker._trimDate(value, minDate, maxDate);
+ }
dateTime = new Date(value.getTime());
} else {
dateTime = (nativePicker instanceof android.widget.DatePicker) ? getDateToday() : getDateNow();
}
const alertDialog = new android.app.AlertDialog.Builder(context);
- const dialogClickListener = new DialogClickListener(nativePicker, dateTime, callback);
- const dialogDismissListener = new DialogDismissListener(callback);
+ const dialogListener = new DialogListener(nativePicker, dateTime, callback);
if (options.title) {
alertDialog.setTitle(options.title);
}
- alertDialog.setOnDismissListener(dialogDismissListener);
+ alertDialog.setOnDismissListener(dialogListener);
const cancelButtonText = options.cancelButtonText ? options.cancelButtonText : this._defaultCancelText;
const okButtonText = options.okButtonText ? options.okButtonText : this._defaultOkText;
- alertDialog.setNegativeButton(cancelButtonText, dialogClickListener);
- alertDialog.setPositiveButton(okButtonText, dialogClickListener);
+ alertDialog.setNegativeButton(cancelButtonText, dialogListener);
+ alertDialog.setPositiveButton(okButtonText, dialogListener);
alertDialog.setView(nativePicker);
return alertDialog;
}
@@ -207,6 +193,17 @@ export class DateTimePicker extends DateTimePickerBase {
}
}
+ private static _trimDate(originalDate: Date, minDate: Date, maxDate: Date) {
+ let finalDate = originalDate;
+ if (minDate !== undefined && minDate > finalDate) {
+ finalDate = minDate;
+ }
+ if (maxDate !== undefined && maxDate < finalDate) {
+ finalDate = maxDate;
+ }
+ return finalDate;
+ }
+
private static _applyDialogColors(nativeDialog: android.app.AlertDialog, color: Color, backgroundColor: Color) {
if (backgroundColor) {
nativeDialog.getWindow().setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(backgroundColor.android));
diff --git a/src/datetimepicker.common.ts b/src/datetimepicker.common.ts
index edc4cd5..058dd35 100644
--- a/src/datetimepicker.common.ts
+++ b/src/datetimepicker.common.ts
@@ -75,20 +75,6 @@ export class DateTimePickerStyleBase implements DateTimePickerStyleDefinition {
}
}
-export function getDateNow(): Date {
- const date = new Date();
- date.setSeconds(0);
- date.setMilliseconds(0);
- return date;
-}
-
-export function getDateToday(): Date {
- const date = getDateNow();
- date.setMinutes(0);
- date.setHours(0);
- return date;
-}
-
export function getCurrentPage(): Page {
let topmostFrame = frameModule.topmost();
if (topmostFrame) {
diff --git a/src/datetimepicker.ios.ts b/src/datetimepicker.ios.ts
index f1a1446..f56b1ec 100644
--- a/src/datetimepicker.ios.ts
+++ b/src/datetimepicker.ios.ts
@@ -1,17 +1,24 @@
import { Color } from "tns-core-modules/color";
import { View, ios as iosView } from "tns-core-modules/ui/core/view";
+import { device } from "tns-core-modules/platform";
import {
- DateTimePickerBase, DateTimePickerStyleBase, getDateNow, getDateToday, getCurrentPage,
+ DateTimePickerBase, DateTimePickerStyleBase, getCurrentPage,
DatePickerOptions, TimePickerOptions, PickerOptions
} from "./datetimepicker.common";
import { LocalizationUtils } from "./utils/localization-utils";
+import { getDateNow, getDateToday } from "./utils/date-utils";
export class DateTimePickerStyle extends DateTimePickerStyleBase {
}
export class DateTimePicker extends DateTimePickerBase {
+ private static readonly SUPPORT_DATE_PICKER_STYLE = parseFloat(device.osVersion) >= 14.0;
+ private static readonly SUPPORT_TEXT_COLOR = parseFloat(device.osVersion) < 14.0;
+ private static readonly DEFAULT_DATE_PICKER_STYLE = 1;
+
public static PICKER_DEFAULT_MESSAGE_HEIGHT = 192;
public static PICKER_WIDTH_INSETS = 16;
+ public static PICKER_WIDTH_PAD = 304;
public static PICKER_DEFAULT_TITLE_OFFSET = 26.5;
public static PICKER_DEFAULT_TITLE_HEIGHT = 16;
public static PICKER_DEFAULT_MESSAGE = "\n\n\n\n\n\n\n\n\n";
@@ -41,6 +48,9 @@ export class DateTimePicker extends DateTimePickerBase {
static _createNativeDatePicker(options: DatePickerOptions): UIDatePicker {
const pickerView = UIDatePicker.alloc().initWithFrame(CGRectZero);
pickerView.datePickerMode = UIDatePickerMode.Date;
+ if (this.SUPPORT_DATE_PICKER_STYLE) {
+ (pickerView as any).preferredDatePickerStyle = this.DEFAULT_DATE_PICKER_STYLE;
+ }
const date = options.date ? options.date : getDateToday();
pickerView.date = date;
if (options.maxDate) {
@@ -58,6 +68,9 @@ export class DateTimePicker extends DateTimePickerBase {
static _createNativeTimePicker(options: TimePickerOptions): UIDatePicker {
const pickerView = UIDatePicker.alloc().initWithFrame(CGRectZero);
pickerView.datePickerMode = UIDatePickerMode.Time;
+ if (this.SUPPORT_DATE_PICKER_STYLE) {
+ (pickerView as any).preferredDatePickerStyle = this.DEFAULT_DATE_PICKER_STYLE;
+ }
const time = options.time ? options.time : getDateNow();
pickerView.date = time;
if (options.locale) {
@@ -71,15 +84,15 @@ export class DateTimePicker extends DateTimePickerBase {
const alertController = UIAlertController.alertControllerWithTitleMessagePreferredStyle(
alertTitle, DateTimePicker.PICKER_DEFAULT_MESSAGE, UIAlertControllerStyle.ActionSheet);
const alertSize = Math.min(alertController.view.frame.size.width, alertController.view.frame.size.height);
- const pickerViewWidth = alertSize - DateTimePicker.PICKER_WIDTH_INSETS;
+ const pickerViewWidth = UIDevice.currentDevice.userInterfaceIdiom === UIUserInterfaceIdiom.Pad ?
+ DateTimePicker.PICKER_WIDTH_PAD : alertSize - DateTimePicker.PICKER_WIDTH_INSETS;
let pickerContainerFrameTop = DateTimePicker.PICKER_DEFAULT_TITLE_OFFSET;
if (options.title) {
pickerContainerFrameTop += DateTimePicker.PICKER_DEFAULT_TITLE_HEIGHT;
}
const pickerViewHeight = DateTimePicker.PICKER_DEFAULT_MESSAGE_HEIGHT;
- const pickerContainerFrame = CGRectMake(0, pickerContainerFrameTop, pickerViewWidth, pickerViewHeight);
- const pickerContainer = UIView.alloc().initWithFrame(pickerContainerFrame);
+ const pickerContainer = UIView.alloc().init();
let spinnersBackgroundColor = new Color("transparent");
let spinnersTextColor = null;
if (style) {
@@ -91,12 +104,22 @@ export class DateTimePicker extends DateTimePickerBase {
const pickerView = nativePicker;
pickerView.frame = CGRectMake(0, 0, pickerViewWidth, pickerViewHeight);
pickerContainer.addSubview(pickerView);
+ DateTimePicker._clearVibrancyEffects(alertController.view);
const messageLabel = DateTimePicker._findLabelWithText(alertController.view, DateTimePicker.PICKER_DEFAULT_MESSAGE);
- const messageLabelContainer = messageLabel.superview;
+ const messageLabelContainer = DateTimePicker._getLabelContainer(messageLabel);
messageLabelContainer.clipsToBounds = true;
messageLabelContainer.addSubview(pickerContainer);
+ pickerContainer.translatesAutoresizingMaskIntoConstraints = false;
+ pickerContainer.topAnchor.constraintEqualToAnchorConstant(alertController.view.topAnchor, pickerContainerFrameTop).active = true;
+ pickerContainer.leftAnchor.constraintEqualToAnchor(alertController.view.leftAnchor).active = true;
+ pickerContainer.rightAnchor.constraintEqualToAnchor(alertController.view.rightAnchor).active = true;
+ pickerContainer.bottomAnchor.constraintEqualToAnchor(alertController.view.bottomAnchor).active = true;
+
+ pickerView.leftAnchor.constraintLessThanOrEqualToAnchorConstant(pickerContainer.leftAnchor, DateTimePicker.PICKER_WIDTH_INSETS).active = true;
+ pickerView.rightAnchor.constraintLessThanOrEqualToAnchorConstant(pickerContainer.rightAnchor, DateTimePicker.PICKER_WIDTH_INSETS).active = true;
+
const cancelButtonText = options.cancelButtonText ? options.cancelButtonText : "Cancel";
const okButtonText = options.okButtonText ? options.okButtonText : "OK";
const cancelActionStyle = (style && style.buttonCancelBackgroundColor) ? UIAlertActionStyle.Default : UIAlertActionStyle.Cancel;
@@ -165,7 +188,10 @@ export class DateTimePicker extends DateTimePickerBase {
nativeContainer.backgroundColor = backgroundColor.ios;
}
if (color) {
- nativePicker.setValueForKey(color.ios, "textColor");
+ if (this.SUPPORT_TEXT_COLOR) {
+ nativePicker.setValueForKey(color, 'textColor');
+ }
+ nativePicker.setValueForKey(false, "highlightsToday");
}
}
@@ -198,6 +224,25 @@ export class DateTimePicker extends DateTimePickerBase {
}
}
+ private static _clearVibrancyEffects(uiView: UIView) {
+ if (uiView instanceof UIVisualEffectView && uiView.effect instanceof UIVibrancyEffect) {
+ // Since ios13 UIAlertController has some effects which cause
+ // semi-transparency and interfere with color customizations:
+ uiView.effect = null;
+ }
+ const subViewsCount = uiView.subviews.count;
+ for (let i = 0; i < subViewsCount; i++) {
+ DateTimePicker._clearVibrancyEffects(uiView.subviews[i]);
+ }
+ }
+
+ private static _getLabelContainer(uiView: UIView) {
+ if (uiView.superview.class() === (UIView.class())) {
+ return uiView.superview;
+ }
+ return DateTimePicker._getLabelContainer(uiView.superview);
+ }
+
private static _findLabelWithText(uiView: UIView, text: string) {
if ((uiView instanceof UILabel) && uiView.text === text) {
return uiView;
@@ -211,4 +256,4 @@ export class DateTimePicker extends DateTimePickerBase {
}
return null;
}
-}
\ No newline at end of file
+}
diff --git a/src/index.d.ts b/src/index.d.ts
index e986427..38410b0 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -1,3 +1,4 @@
export * from "./datetimepicker";
export * from "./ui/date-picker-field";
export * from "./ui/time-picker-field";
+export * from "./ui/date-time-picker-fields";
diff --git a/src/index.ts b/src/index.ts
index 7b57192..4eb037f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,4 @@
export * from "./datetimepicker";
export * from "./ui/date-picker-field";
-export * from "./ui/time-picker-field";
\ No newline at end of file
+export * from "./ui/time-picker-field";
+export * from "./ui/date-time-picker-fields";
\ No newline at end of file
diff --git a/src/package.json b/src/package.json
index f98121a..287eca0 100644
--- a/src/package.json
+++ b/src/package.json
@@ -1,81 +1,80 @@
{
- "name": "nativescript-datetimepicker",
- "version": "1.1.0",
- "description": "A NativeScript plugin for picking date and time.",
- "typings": "index.d.ts",
- "nativescript": {
- "platforms": {
- "android": "5.0.0",
- "ios": "5.0.0"
- }
- },
- "scripts": {
- "tsc": "npm i && tsc",
- "build": "npm run tsc",
- "tslint": "cd .. && tslint \"**/*.ts\" --config tslint.json --exclude \"**/node_modules/**\" --exclude \"**/platforms/**\"",
- "plugin.tscwatch": "npm run tsc -- -w",
- "demo.ios": "npm run build && cd ../demo && tns run ios --syncAllFiles --emulator",
- "demo.android": "npm run build && cd ../demo && tns run android --syncAllFiles --emulator",
- "demo.reset": "cd ../demo && npx rimraf -- hooks node_modules platforms package-lock.json",
- "demo.ng.ios": "npm run build && cd ../demo-angular && tns run ios --syncAllFiles --emulator",
- "demo.ng.android": "npm run build && cd ../demo-angular && tns run android --syncAllFiles --emulator",
- "demo.ng.reset": "cd ../demo-angular && npx rimraf -- hooks node_modules platforms package-lock.json",
- "demo.vue.ios": "npm run build && cd ../demo-vue && tns run ios --bundle --syncAllFiles --emulator",
- "demo.vue.android": "npm run build && cd ../demo-vue && tns run android --bundle --syncAllFiles --emulator",
- "demo.vue.reset": "cd ../demo-vue && npx rimraf -- hooks node_modules platforms package-lock.json",
- "plugin.prepare": "npm run build && cd ../demo && tns plugin remove nativescript-datetimepicker && tns plugin add ../src",
- "clean": "npm run demo.reset && npx rimraf -- node_modules package-lock.json && npm i",
- "ci.tslint": "npm i && tslint '**/*.ts' --config '../tslint.json' --exclude '**/node_modules/**' --exclude '**/platforms/**'",
- "ngc": "ngc -p tsconfig.json",
- "prepack": "npm i && npm run ngc",
- "pack": "bash ../publish/pack.sh"
- },
- "keywords": [
- "NativeScript",
- "JavaScript",
- "Android",
- "iOS",
- "DatePicker",
- "TimePicker",
- "Date",
- "Time"
- ],
- "author": {
- "name": "NativeScript Team",
- "email": "nativescriptplugins@progress.com"
- },
- "bugs": {
- "url": "https://github.com/NativeScript/nativescript-datetimepicker/issues"
- },
- "repository": {
- "type": "git",
- "url": "git://github.com/NativeScript/nativescript-datetimepicker.git"
- },
- "license": "Apache-2.0",
- "homepage": "https://github.com/NativeScript/nativescript-datetimepicker",
- "readmeFilename": "README.md",
- "devDependencies": {
- "tns-core-modules": "^5.0.0",
- "tns-platform-declarations": "^5.0.0",
- "typescript": "~3.1.6",
- "prompt": "^1.0.0",
- "rimraf": "^2.6.2",
- "tslint": "^5.11.0",
- "semver": "^5.6.0",
- "nativescript-angular": "~7.2.0",
- "@angular/core": "~7.2.0",
- "@angular/common": "~7.2.0",
- "@angular/compiler": "~7.2.0",
- "@angular/compiler-cli": "~7.2.0",
- "@angular/forms": "~7.2.0",
- "@angular/http": "~7.2.0",
- "@angular/platform-browser": "~7.2.0",
- "@angular/platform-browser-dynamic": "~7.2.0",
- "@angular/router": "~7.2.0",
- "rxjs": "~6.4.0",
- "zone.js": "~0.8.26",
- "nativescript-vue": "~2.0.0"
- },
- "dependencies": {},
- "bootstrapper": "nativescript-plugin-seed"
+ "name": "nativescript-datetimepicker",
+ "version": "1.2.3",
+ "description": "A NativeScript plugin for picking date and time.",
+ "typings": "index.d.ts",
+ "nativescript": {
+ "platforms": {
+ "android": "5.0.0",
+ "ios": "5.0.0"
+ }
+ },
+ "scripts": {
+ "tsc": "npm i && tsc",
+ "build": "npm run tsc && npm run ngc",
+ "tslint": "cd .. && tslint \"**/*.ts\" --config tslint.json --exclude \"**/node_modules/**\" --exclude \"**/platforms/**\"",
+ "plugin.tscwatch": "npm run tsc -- -w",
+ "demo.ios": "npm run build && cd ../demo && tns run ios --emulator",
+ "demo.android": "npm run build && cd ../demo && tns run android --emulator",
+ "demo.reset": "cd ../demo && npx rimraf -- hooks node_modules platforms package-lock.json",
+ "demo.ng.ios": "npm run build && cd ../demo-angular && tns run ios --emulator",
+ "demo.ng.android": "npm run build && cd ../demo-angular && tns run android --emulator",
+ "demo.ng.reset": "cd ../demo-angular && npx rimraf -- hooks node_modules platforms package-lock.json",
+ "demo.vue.ios": "npm run build && cd ../demo-vue && tns run ios --emulator",
+ "demo.vue.android": "npm run build && cd ../demo-vue && tns run android --emulator",
+ "demo.vue.reset": "cd ../demo-vue && npx rimraf -- hooks node_modules platforms package-lock.json",
+ "plugin.prepare": "npm run build && cd ../demo && tns plugin remove nativescript-datetimepicker && tns plugin add ../src",
+ "clean": "npm run demo.reset && npx rimraf -- node_modules package-lock.json && npm i",
+ "ci.tslint": "npm i && tslint '**/*.ts' --config '../tslint.json' --exclude '**/node_modules/**' --exclude '**/platforms/**'",
+ "ngc": "ngc -p tsconfig.json",
+ "prepack": "npm i && npm run ngc",
+ "pack": "bash ../publish/pack.sh"
+ },
+ "keywords": [
+ "NativeScript",
+ "JavaScript",
+ "Android",
+ "iOS",
+ "DatePicker",
+ "TimePicker",
+ "Date",
+ "Time"
+ ],
+ "author": {
+ "name": "NativeScript Team",
+ "email": "nativescriptplugins@progress.com"
+ },
+ "bugs": {
+ "url": "https://github.com/NativeScript/nativescript-datetimepicker/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/NativeScript/nativescript-datetimepicker.git"
+ },
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/NativeScript/nativescript-datetimepicker",
+ "readmeFilename": "README.md",
+ "devDependencies": {
+ "@angular/common": "~8.2.0",
+ "@angular/compiler": "~8.2.0",
+ "@angular/compiler-cli": "~8.2.0",
+ "@angular/core": "~8.2.0",
+ "@angular/forms": "~8.2.0",
+ "@angular/platform-browser": "~8.2.0",
+ "@angular/platform-browser-dynamic": "~8.2.0",
+ "@angular/router": "~8.2.0",
+ "nativescript-angular": "~8.20.0",
+ "nativescript-vue": "~2.4.0",
+ "prompt": "^1.0.0",
+ "rimraf": "^2.6.2",
+ "rxjs": "^6.3.3",
+ "semver": "^5.6.0",
+ "tns-core-modules": "~6.5.0",
+ "tns-platform-declarations": "~6.0.0",
+ "tslint": "^5.11.0",
+ "typescript": "~3.5.3",
+ "zone.js": "^0.8.4"
+ },
+ "dependencies": {},
+ "bootstrapper": "nativescript-plugin-seed"
}
diff --git a/src/ui/date-picker-field.common.ts b/src/ui/date-picker-field.common.ts
index 094cedd..d37c6dc 100644
--- a/src/ui/date-picker-field.common.ts
+++ b/src/ui/date-picker-field.common.ts
@@ -1,7 +1,8 @@
-import { Property, CSSType } from "tns-core-modules/ui/core/view";
+import { Property, CSSType, EventData } from "tns-core-modules/ui/core/view";
import { DateTimePicker, DateTimePickerStyle } from "../datetimepicker";
import { DatePickerField as DatePickerFieldDefinition } from "./date-picker-field";
import { LocalizationUtils } from "../utils/localization-utils";
+import { getDateToday, dateComparer } from "../utils/date-utils";
import { PickerFieldBase } from "./picker-field-base";
@CSSType("DatePickerField")
@@ -11,6 +12,8 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
public date: Date;
public dateFormat: string;
public pickerDefaultDate: Date;
+ public static datePickerOpenedEvent = "datePickerOpened";
+ public static datePickerClosedEvent = "datePickerClosed";
private _nativeLocale: any;
private _nativeDateFormatter: any;
@@ -41,6 +44,7 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
public static pickerDefaultDateProperty = new Property({
name: "pickerDefaultDate",
+ defaultValue: getDateToday(),
equalityComparer: dateComparer,
valueConverter: dateValueConverter,
});
@@ -61,10 +65,20 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
if (result) {
this.date = result;
}
+ let args = {
+ eventName: DatePickerFieldBase.datePickerClosedEvent,
+ object: this
+ };
+ this.notify(args);
})
.catch((err) => {
console.log('DatePickerField Error: ' + err);
});
+ let args = {
+ eventName: DatePickerFieldBase.datePickerOpenedEvent,
+ object: this
+ };
+ this.notify(args);
}
public updateText() {
@@ -110,10 +124,6 @@ export class DatePickerFieldBase extends PickerFieldBase implements DatePickerFi
}
}
-export function dateComparer(x: Date, y: Date): boolean {
- return x <= y && x >= y;
-}
-
export function dateValueConverter(v: any): Date {
return new Date(v);
}
diff --git a/src/ui/date-time-picker-fields.d.ts b/src/ui/date-time-picker-fields.d.ts
new file mode 100644
index 0000000..db32b9a
--- /dev/null
+++ b/src/ui/date-time-picker-fields.d.ts
@@ -0,0 +1,194 @@
+/**
+ * Contains the DatePickerField class.
+ */
+import { Property, View } from "tns-core-modules/ui/core/view";
+import { GridLayout } from "tns-core-modules/ui/layouts/grid-layout";
+import { Orientation } from "tns-core-modules/ui/layouts/stack-layout";
+
+/**
+ * Represents a TextField that can be tapped to open a picker. The picker is a dialog with
+ * date picking spinners along with OK/Cancel buttons.
+ */
+export class DateTimePickerFields extends GridLayout {
+ /**
+ * Gets or sets the selected date.
+ */
+ date: Date;
+
+ /**
+ * Gets or sets the max date. Note that this property only affects the date component.
+ */
+ maxDate: Date;
+
+ /**
+ * Gets or sets the min date. Note that this property only affects the date component.
+ */
+ minDate: Date;
+
+ /**
+ * Gets or sets a format for displaying the date in the field.
+ * Default value is undefined, meaning that the format will be based on the current locale.
+ * Here are some examples with the way 1st of April, 2019 is displayed for each of the formats:
+ * MMM dd, yyyy - Apr 01, 2019
+ * d.M.yy - 1.4.19
+ * EEE, d MMMM yyyy - Mon, 1 April 2019
+ */
+ dateFormat: string;
+
+ /**
+ * Gets or sets a format for displaying the date in the field.
+ * Default value is undefined, meaning that the format will be based on the current locale.
+ * Here are some examples with the way 1st of April, 2019 is displayed for each of the formats:
+ * MMM dd, yyyy - Apr 01, 2019
+ * d.M.yy - 1.4.19
+ * EEE, d MMMM yyyy - Mon, 1 April 2019
+ */
+ timeFormat: string;
+
+ /**
+ * Gets or sets a locale for displaying the date in the field, and also for the picker.
+ * Default value is undefined, meaning that the format will be based on the device's settings.
+ * In order to fixate the date to English, you can use English-based locales like: en_US, en_UK, etc.
+ * If you want to provide localization for your app, you can supply different locales, depending
+ * on the selected setting.
+ * Note that changing the locale will not affect the {@link pickerOkText}, {@link pickerCancelText}
+ * and {@link pickerTitle} or {@link hint} properties.
+ */
+ locale: string;
+
+ /**
+ * Gets or sets the hint text for the date component. Hint is the text that is displayed in a field when {@link date} is null.
+ */
+ hintDate: string;
+
+ /**
+ * Gets or sets the hint text for the time component. Hint is the text that is displayed in a field when {@link date} is null.
+ */
+ hintTime: string;
+
+ /**
+ * Gets or sets the date that will be initially selected in the picker when {@link date} is null.
+ *
+ * @default now
+ */
+ pickerDefaultDate: Date;
+
+ /**
+ * Gets or sets the title for picker selecting date. The title is the text that is displayed in the picker
+ * above the date selecting spinners.
+ */
+ pickerTitleDate: string;
+
+ /**
+ * Gets or sets the title for picker selecting time. The title is the text that is displayed in the picker
+ * above the time selecting spinners.
+ */
+ pickerTitleTime: string;
+
+ /**
+ * Gets or sets the text of the button in the picker that is used to confirm the selection.
+ * By default, on iOS the text will be OK, while on android the text will be
+ * determined by the current device's localization settings. Please note, that the value
+ * is not related with the value {@link locale} property.
+ */
+ pickerOkText: string;
+
+ /**
+ * Gets or sets the text of the button in the picker that is used to dismiss the picker,
+ * and cancel the current date selection.
+ * By default, on iOS the text will be Cancel, while on android the text will be
+ * determined by the current device's localization settings. Please note, that the value
+ * is not related with the value {@link locale} property.
+ */
+ pickerCancelText: string;
+
+ /**
+ * Gets or sets a value that indicates whether the time should be assigned a value as soon as date is picked.
+ *
+ * @default false
+ */
+ autoPickTime: boolean;
+
+ /**
+ * Gets or sets a value that indicates whether the date and time components should be on the same row or not.
+ * Default value is horizontal, meaning that the two fields will be on the same row.
+ *
+ * @default horizontal
+ */
+ orientation: Orientation;
+
+ /**
+ * Identifies the {@link date} dependency property.
+ */
+ static dateProperty: Property;
+
+ /**
+ * Identifies the {@link maxDate} dependency property.
+ */
+ static maxDateProperty: Property;
+
+ /**
+ * Identifies the {@link minDate} dependency property.
+ */
+ static minDateProperty: Property;
+
+ /**
+ * Identifies the {@link dateFormat} dependency property.
+ */
+ static dateFormatProperty: Property;
+
+ /**
+ * Identifies the {@link timeFormat} dependency property.
+ */
+ static timeFormatProperty: Property;
+
+ /**
+ * Identifies the {@link locale} dependency property.
+ */
+ static localeProperty: Property;
+
+ /**
+ * Identifies the {@link hintDate} dependency property.
+ */
+ static hintDateProperty: Property;
+
+ /**
+ * Identifies the {@link hintTime} dependency property.
+ */
+ static hintTimeProperty: Property;
+
+ /**
+ * Identifies the {@link pickerDefaultDate} dependency property.
+ */
+ static pickerDefaultDateProperty: Property;
+
+ /**
+ * Identifies the {@link pickerTitleDate} dependency property.
+ */
+ static pickerTitleDateProperty: Property;
+
+ /**
+ * Identifies the {@link pickerTitleTime} dependency property.
+ */
+ static pickerTitleTimeProperty: Property;
+
+ /**
+ * Identifies the {@link pickerOkText} dependency property.
+ */
+ static pickerOkTextProperty: Property;
+
+ /**
+ * Identifies the {@link pickerCancelText} dependency property.
+ */
+ static pickerCancelTextProperty: Property;
+
+ /**
+ * Identifies the {@link autoPickTime} dependency property.
+ */
+ static autoPickTimeProperty: Property;
+
+ /**
+ * Identifies the {@link orientation} dependency property.
+ */
+ static orientationProperty: Property;
+}
\ No newline at end of file
diff --git a/src/ui/date-time-picker-fields.ts b/src/ui/date-time-picker-fields.ts
new file mode 100644
index 0000000..555d502
--- /dev/null
+++ b/src/ui/date-time-picker-fields.ts
@@ -0,0 +1,331 @@
+import { Property, CSSType, EventData } from "tns-core-modules/ui/core/view";
+import { PropertyChangeData } from "tns-core-modules/data/observable";
+import { DateTimePickerFields as DateTimePickerFieldsDefinition } from "./date-time-picker-fields";
+import { GridLayout, ItemSpec } from "tns-core-modules/ui/layouts/grid-layout";
+import { Orientation } from "tns-core-modules/ui/layouts/stack-layout";
+import { DatePickerField } from "./date-picker-field";
+import { TimePickerField } from "./time-picker-field";
+import { getDateNow, clearTime, dateComparer } from "../utils/date-utils";
+
+@CSSType("DateTimePickerFields")
+export class DateTimePickerFields extends GridLayout implements DateTimePickerFieldsDefinition {
+ public dateField: DatePickerField;
+ public timeField: TimePickerField;
+
+ public date: Date;
+
+ public maxDate: Date;
+ public minDate: Date;
+
+ public dateFormat: string;
+ public timeFormat: string;
+ public locale: string;
+ public hintDate: string;
+ public hintTime: string;
+
+ public pickerDefaultDate: Date;
+ public pickerTitleDate: string;
+ public pickerTitleTime: string;
+ public pickerOkText: string;
+ public pickerCancelText: string;
+
+ public orientation: Orientation;
+ public autoPickTime: boolean;
+
+ _shouldSkipTimeAssignment: boolean;
+
+ private _dateChangeHandler: (args: PropertyChangeData) => void;
+ private _timeChangeHandler: (args: PropertyChangeData) => void;
+
+ constructor() {
+ super();
+ this.dateField = new DatePickerField();
+ this.timeField = new TimePickerField();
+
+ let row1Spec = new ItemSpec(1, "star");
+ let row2Spec = new ItemSpec(1, "star");
+ let column1Spec = new ItemSpec(1, "star");
+ let column2Spec = new ItemSpec(1, "star");
+
+ this.addRow(row1Spec);
+ this.addRow(row2Spec);
+ this.addColumn(column1Spec);
+ this.addColumn(column2Spec);
+
+ this.addChild(this.dateField);
+ this.addChild(this.timeField);
+
+ DateTimePickerFields._updateOrientation(this);
+ }
+
+ public static dateProperty = new Property({
+ name: "date",
+ equalityComparer: dateComparer,
+ valueConverter: dateValueConverter,
+ valueChanged: DateTimePickerFields.datePropertyChanged
+ });
+
+ public static maxDateProperty = new Property({
+ name: "maxDate",
+ equalityComparer: dateComparer,
+ valueConverter: dateValueConverter,
+ valueChanged: DateTimePickerFields.maxDatePropertyChanged
+ });
+
+ public static minDateProperty = new Property({
+ name: "minDate",
+ equalityComparer: dateComparer,
+ valueConverter: dateValueConverter,
+ valueChanged: DateTimePickerFields.minDatePropertyChanged
+ });
+
+ public static dateFormatProperty = new Property({
+ name: "dateFormat",
+ valueChanged: DateTimePickerFields.dateFormatPropertyChanged,
+ });
+
+ public static timeFormatProperty = new Property({
+ name: "timeFormat",
+ valueChanged: DateTimePickerFields.timeFormatPropertyChanged,
+ });
+
+ public static localeProperty = new Property({
+ name: "locale",
+ valueChanged: DateTimePickerFields.localePropertyChanged
+ });
+
+ public static hintDateProperty = new Property({
+ name: "hintDate",
+ valueChanged: DateTimePickerFields.hintDatePropertyChanged,
+ });
+
+ public static hintTimeProperty = new Property({
+ name: "hintTime",
+ valueChanged: DateTimePickerFields.hintTimePropertyChanged,
+ });
+
+ public static pickerDefaultDateProperty = new Property({
+ name: "pickerDefaultDate",
+ defaultValue: getDateNow(),
+ equalityComparer: dateComparer,
+ valueConverter: dateValueConverter,
+ valueChanged: DateTimePickerFields.pickerDefaultDatePropertyChanged
+ });
+
+ public static pickerTitleDateProperty = new Property({
+ name: "pickerTitleDate",
+ valueChanged: DateTimePickerFields.pickerTitleDatePropertyChanged
+ });
+
+ public static pickerTitleTimeProperty = new Property({
+ name: "pickerTitleTime",
+ valueChanged: DateTimePickerFields.pickerTitleTimePropertyChanged
+ });
+
+ public static pickerOkTextProperty = new Property({
+ name: "pickerOkText",
+ valueChanged: DateTimePickerFields.pickerOkTextPropertyChanged
+ });
+
+ public static pickerCancelTextProperty = new Property({
+ name: "pickerCancelText",
+ valueChanged: DateTimePickerFields.pickerCancelTextPropertyChanged
+ });
+
+ public static orientationProperty = new Property({
+ name: "orientation",
+ defaultValue: "horizontal",
+ valueChanged: DateTimePickerFields.orientationPropertyChanged
+ });
+
+ public static autoPickTimeProperty = new Property({
+ name: "autoPickTime",
+ defaultValue: false,
+ valueChanged: DateTimePickerFields.autoPickTimePropertyChanged
+ });
+
+ private static datePropertyChanged(field: DateTimePickerFields, oldValue: Date, newValue: Date) {
+ field.dateField.date = newValue;
+ if (!field._shouldSkipTimeAssignment) {
+ field.timeField.time = newValue;
+ }
+ field._shouldSkipTimeAssignment = false;
+ }
+
+ private static maxDatePropertyChanged(field: DateTimePickerFields, oldValue: Date, newValue: Date) {
+ field.dateField.maxDate = newValue;
+ }
+
+ private static minDatePropertyChanged(field: DateTimePickerFields, oldValue: Date, newValue: Date) {
+ field.dateField.minDate = newValue;
+ }
+
+ private static dateFormatPropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.dateField.dateFormat = newValue;
+ }
+
+ private static timeFormatPropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.timeField.timeFormat = newValue;
+ }
+
+ private static localePropertyChanged(field: DateTimePickerFields, oldValue: any, newValue: any) {
+ field.dateField.locale = newValue;
+ field.timeField.locale = newValue;
+ }
+
+ private static hintDatePropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.dateField.hint = newValue;
+ }
+
+ private static hintTimePropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.timeField.hint = newValue;
+ }
+
+ private static pickerDefaultDatePropertyChanged(field: DateTimePickerFields, oldValue: Date, newValue: Date) {
+ field.dateField.pickerDefaultDate = newValue;
+ field.timeField.pickerDefaultTime = newValue;
+ }
+
+ private static pickerTitleDatePropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.dateField.pickerTitle = newValue;
+ }
+
+ private static pickerTitleTimePropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.timeField.pickerTitle = newValue;
+ }
+
+ private static pickerOkTextPropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.dateField.pickerOkText = newValue;
+ field.timeField.pickerOkText = newValue;
+ }
+
+ private static pickerCancelTextPropertyChanged(field: DateTimePickerFields, oldValue: string, newValue: string) {
+ field.dateField.pickerCancelText = newValue;
+ field.timeField.pickerCancelText = newValue;
+ }
+
+ private static orientationPropertyChanged(field: DateTimePickerFields, oldValue: Orientation, newValue: Orientation) {
+ DateTimePickerFields._updateOrientation(field);
+ }
+
+ private static autoPickTimePropertyChanged(field: DateTimePickerFields, oldValue: boolean, newValue: boolean) {
+ if (field.autoPickTime) {
+ field.dateField.pickerDefaultDate = field.pickerDefaultDate;
+ } else {
+ field.dateField.pickerDefaultDate = clearTime(field.pickerDefaultDate);
+ }
+ }
+
+ createNativeView() {
+ const nativeView = super.createNativeView();
+ const ngKey = Object.keys(this).find(key => key.startsWith('_ngcontent'));
+ const vueKey = Object.keys(this).find(key => key.startsWith('data-v'));
+ if (ngKey) {
+ this.dateField[ngKey] = this[ngKey];
+ this.timeField[ngKey] = this[ngKey];
+ }
+ if (vueKey) {
+ this.dateField[vueKey] = this[vueKey];
+ this.timeField[vueKey] = this[vueKey];
+ }
+ return nativeView;
+ }
+
+ initNativeView() {
+ super.initNativeView();
+ this._updateHandlers(true);
+ }
+
+ disposeNativeView() {
+ this._updateHandlers(false);
+ super.disposeNativeView();
+ }
+
+ public addEventListener(eventNames: string, callback: (data: EventData) => void, thisArg?: Object) {
+ super.addEventListener(eventNames, callback, thisArg);
+ this.dateField.addEventListener(eventNames, callback, thisArg);
+ this.timeField.addEventListener(eventNames, callback, thisArg);
+ }
+ public removeEventListener(eventNames: string, callback?: any, thisArg?: Object) {
+ super.removeEventListener(eventNames, callback, thisArg);
+ this.dateField.removeEventListener(eventNames, callback, thisArg);
+ this.timeField.removeEventListener(eventNames, callback, thisArg);
+ }
+
+ private _updateHandlers(subscribe: boolean) {
+ if (subscribe) {
+ this._dateChangeHandler = this._dateChangeHandler || ((args: PropertyChangeData) => {
+ if (args.propertyName === "date") {
+ if (!this.autoPickTime && this.timeField.time === undefined) {
+ this._shouldSkipTimeAssignment = true;
+ }
+ this.date = args.value;
+ }
+ });
+ this.dateField.on("dateChange", this._dateChangeHandler);
+ this._timeChangeHandler = this._timeChangeHandler || ((args: PropertyChangeData) => {
+ if (args.propertyName === "time") {
+ this.date = args.value;
+ }
+ });
+ this.timeField.on("timeChange", this._timeChangeHandler);
+ if (this.className) {
+ this._handleClassNameChange();
+ }
+ this.on("classNameChange", this._handleClassNameChange, this);
+ } else {
+ this.dateField.off("dateChange", this._dateChangeHandler);
+ this.timeField.off("timeChange", this._timeChangeHandler);
+ this.off("classNameChange", this._handleClassNameChange);
+ }
+ }
+
+ private _handleClassNameChange() {
+ if (this.dateField && this.timeField) {
+ this.dateField.className = this.className;
+ this.timeField.className = this.className;
+ }
+ }
+
+ private static _updateOrientation(field: DateTimePickerFields) {
+ if (field.orientation === "horizontal") {
+ GridLayout.setRow(field.dateField, 0);
+ GridLayout.setRow(field.timeField, 0);
+ GridLayout.setColumn(field.dateField, 0);
+ GridLayout.setColumn(field.timeField, 1);
+ GridLayout.setRowSpan(field.dateField, 2);
+ GridLayout.setRowSpan(field.timeField, 2);
+ GridLayout.setColumnSpan(field.dateField, 1);
+ GridLayout.setColumnSpan(field.timeField, 1);
+ } else if (field.orientation === "vertical") {
+ GridLayout.setRow(field.dateField, 0);
+ GridLayout.setRow(field.timeField, 1);
+ GridLayout.setColumn(field.dateField, 0);
+ GridLayout.setColumn(field.timeField, 0);
+ GridLayout.setRowSpan(field.dateField, 1);
+ GridLayout.setRowSpan(field.timeField, 1);
+ GridLayout.setColumnSpan(field.dateField, 2);
+ GridLayout.setColumnSpan(field.timeField, 2);
+ }
+ }
+}
+
+export function dateValueConverter(v: any): Date {
+ return new Date(v);
+}
+
+DateTimePickerFields.dateProperty.register(DateTimePickerFields);
+DateTimePickerFields.maxDateProperty.register(DateTimePickerFields);
+DateTimePickerFields.minDateProperty.register(DateTimePickerFields);
+DateTimePickerFields.dateFormatProperty.register(DateTimePickerFields);
+DateTimePickerFields.timeFormatProperty.register(DateTimePickerFields);
+DateTimePickerFields.localeProperty.register(DateTimePickerFields);
+DateTimePickerFields.hintDateProperty.register(DateTimePickerFields);
+DateTimePickerFields.hintTimeProperty.register(DateTimePickerFields);
+DateTimePickerFields.pickerDefaultDateProperty.register(DateTimePickerFields);
+DateTimePickerFields.pickerTitleDateProperty.register(DateTimePickerFields);
+DateTimePickerFields.pickerTitleTimeProperty.register(DateTimePickerFields);
+DateTimePickerFields.pickerOkTextProperty.register(DateTimePickerFields);
+DateTimePickerFields.pickerCancelTextProperty.register(DateTimePickerFields);
+DateTimePickerFields.orientationProperty.register(DateTimePickerFields);
+DateTimePickerFields.autoPickTimeProperty.register(DateTimePickerFields);
\ No newline at end of file
diff --git a/src/ui/picker-field-base.ts b/src/ui/picker-field-base.ts
index 231cc46..8071c70 100644
--- a/src/ui/picker-field-base.ts
+++ b/src/ui/picker-field-base.ts
@@ -8,7 +8,7 @@ export abstract class PickerFieldBase extends TextField {
public pickerOkText: string;
public pickerCancelText: string;
- private _tapHandler: (args: TouchGestureEventData) => void;
+ private _pickerFieldBaseTapHandler: (args: TouchGestureEventData) => void;
constructor() {
super();
@@ -36,11 +36,11 @@ export abstract class PickerFieldBase extends TextField {
initNativeView() {
super.initNativeView();
- this._updateHandler(true);
+ this._updatePickerFieldBaseTapHandler(true);
}
disposeNativeView() {
- this._updateHandler(false);
+ this._updatePickerFieldBaseTapHandler(false);
super.disposeNativeView();
}
@@ -51,18 +51,18 @@ export abstract class PickerFieldBase extends TextField {
protected onLocaleChanged(oldValue: string, newValue: string) {
}
- private _updateHandler(subscribe: boolean) {
+ private _updatePickerFieldBaseTapHandler(subscribe: boolean) {
if (subscribe) {
- this._tapHandler = this._tapHandler || ((args: TouchGestureEventData) => {
- this._onTap(args);
+ this._pickerFieldBaseTapHandler = this._pickerFieldBaseTapHandler || ((args: TouchGestureEventData) => {
+ this._onPickerFieldBaseTap(args);
});
- this.on(GestureTypes.tap, this._tapHandler);
+ this.on(GestureTypes.tap, this._pickerFieldBaseTapHandler);
} else {
- this.off(GestureTypes.tap, this._tapHandler);
+ this.off(GestureTypes.tap, this._pickerFieldBaseTapHandler);
}
}
- private _onTap(args: TouchGestureEventData) {
+ private _onPickerFieldBaseTap(args: TouchGestureEventData) {
this.open();
}
}
diff --git a/src/ui/time-picker-field.common.ts b/src/ui/time-picker-field.common.ts
index df1fb09..838e592 100644
--- a/src/ui/time-picker-field.common.ts
+++ b/src/ui/time-picker-field.common.ts
@@ -1,7 +1,8 @@
-import { Property, CSSType } from "tns-core-modules/ui/core/view";
+import { Property, CSSType, EventData } from "tns-core-modules/ui/core/view";
import { DateTimePicker, DateTimePickerStyle } from "../datetimepicker";
import { TimePickerField as TimePickerFieldDefinition } from "./time-picker-field";
import { LocalizationUtils } from "../utils/localization-utils";
+import { getDateNow, dateComparer } from "../utils/date-utils";
import { PickerFieldBase } from "./picker-field-base";
@CSSType("TimePickerField")
@@ -9,13 +10,15 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
public time: Date;
public timeFormat: string;
public pickerDefaultTime: Date;
+ public static timePickerOpenedEvent = "timePickerOpened";
+ public static timePickerClosedEvent = "timePickerClosed";
private _nativeLocale: any;
private _nativeTimeFormatter: any;
public static timeProperty = new Property({
name: "time",
- equalityComparer: timeComparer,
+ equalityComparer: dateComparer,
valueConverter: timeValueConverter,
valueChanged: TimePickerFieldBase.timePropertyChanged
});
@@ -27,7 +30,8 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
public static pickerDefaultTimeProperty = new Property({
name: "pickerDefaultTime",
- equalityComparer: timeComparer,
+ defaultValue: getDateNow(),
+ equalityComparer: dateComparer,
valueConverter: timeValueConverter
});
@@ -46,10 +50,20 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
if (result) {
this.time = result;
}
+ let args = {
+ eventName: TimePickerFieldBase.timePickerClosedEvent,
+ object: this
+ };
+ this.notify(args);
})
.catch((err) => {
console.log('TimePickerField Error: ' + err);
});
+ let args = {
+ eventName: TimePickerFieldBase.timePickerOpenedEvent,
+ object: this
+ };
+ this.notify(args);
}
public updateText() {
@@ -99,10 +113,6 @@ export class TimePickerFieldBase extends PickerFieldBase implements TimePickerFi
}
}
-export function timeComparer(x: Date, y: Date): boolean {
- return x <= y && x >= y;
-}
-
// Creates a date for today with the time represented in the timeString in ISO 8601 formats
// as specified here: https://en.wikipedia.org/wiki/ISO_8601#Times:
// 1)hh:mm:ss.sss --- 2)hhmmss.sss --- 3)hh:mm:ss --- 4)hhmmss --- 5)hh:mm --- 6)hhmm --- 7)hh
diff --git a/src/utils/date-utils.ts b/src/utils/date-utils.ts
new file mode 100644
index 0000000..7f29bd6
--- /dev/null
+++ b/src/utils/date-utils.ts
@@ -0,0 +1,34 @@
+export function getDateNow(): Date {
+ const date = new Date();
+ date.setSeconds(0);
+ date.setMilliseconds(0);
+ return date;
+}
+
+export function getDateToday(): Date {
+ const date = getDateNow();
+ date.setMinutes(0);
+ date.setHours(0);
+ return date;
+}
+
+export function clearTime(date: Date): Date {
+ if (!date) {
+ return date;
+ }
+ date.setHours(0);
+ date.setMinutes(0);
+ date.setSeconds(0);
+ date.setMilliseconds(0);
+ return date;
+}
+
+export function dateComparer(x: Date, y: Date): boolean {
+ if (x === undefined && y === undefined) {
+ return true;
+ }
+ if (x === null && y === null) {
+ return true;
+ }
+ return x <= y && x >= y;
+}
\ No newline at end of file
diff --git a/src/vue/index.ts b/src/vue/index.ts
index 0cf844e..9a655f7 100644
--- a/src/vue/index.ts
+++ b/src/vue/index.ts
@@ -1,5 +1,6 @@
import { DatePickerField } from "../ui/date-picker-field";
import { TimePickerField } from "../ui/time-picker-field";
+import { DateTimePickerFields } from "../ui/date-time-picker-fields";
const DateTimePicker = {
install(Vue) {
@@ -24,6 +25,17 @@ const DateTimePicker = {
}
}
);
+
+ Vue.registerElement(
+ 'DateTimePickerFields',
+ () => DateTimePickerFields,
+ {
+ model: {
+ prop: 'date',
+ event: 'dateChange'
+ }
+ }
+ );
}
};
export default DateTimePicker;
\ No newline at end of file
diff --git a/demo-angular/e2e/config/appium.capabilities.json b/tests/e2e/config/appium.capabilities.json
similarity index 92%
rename from demo-angular/e2e/config/appium.capabilities.json
rename to tests/e2e/config/appium.capabilities.json
index b8c1f53..3e19c7f 100644
--- a/demo-angular/e2e/config/appium.capabilities.json
+++ b/tests/e2e/config/appium.capabilities.json
@@ -80,14 +80,10 @@
},
"android28": {
"platformName": "Android",
- "platformVersion": "28",
- "deviceName": "Emulator-Api28-Google",
- "avd": "Emulator-Api28-Google",
- "lt": 60000,
- "newCommandTimeout": 720,
- "noReset": false,
- "fullReset": false,
- "app": ""
+ "platformVersion": "9.0",
+ "deviceName": "Android GoogleAPI Emulator",
+ "appiumVersion": "1.9.1",
+ "noReset": true
},
"sim.iPhone7": {
"platformName": "iOS",
diff --git a/demo-angular/e2e/config/mocha.opts b/tests/e2e/config/mocha.opts
similarity index 100%
rename from demo-angular/e2e/config/mocha.opts
rename to tests/e2e/config/mocha.opts
diff --git a/demo-angular/e2e/helper.ts b/tests/e2e/helper.ts
similarity index 100%
rename from demo-angular/e2e/helper.ts
rename to tests/e2e/helper.ts
diff --git a/tests/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png b/tests/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png
new file mode 100644
index 0000000..fbd4bef
Binary files /dev/null and b/tests/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png differ
diff --git a/tests/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png b/tests/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png
new file mode 100644
index 0000000..8252547
Binary files /dev/null and b/tests/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png differ
diff --git a/tests/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png b/tests/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png
new file mode 100644
index 0000000..2c2e8ef
Binary files /dev/null and b/tests/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png differ
diff --git a/tests/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png b/tests/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png
new file mode 100644
index 0000000..900abe4
Binary files /dev/null and b/tests/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png differ
diff --git a/demo-angular/e2e/setup.ts b/tests/e2e/setup.ts
similarity index 100%
rename from demo-angular/e2e/setup.ts
rename to tests/e2e/setup.ts
diff --git a/demo-angular/e2e/tests.e2e.ts b/tests/e2e/tests.e2e.ts
similarity index 76%
rename from demo-angular/e2e/tests.e2e.ts
rename to tests/e2e/tests.e2e.ts
index 7acbc59..21fefb4 100644
--- a/demo-angular/e2e/tests.e2e.ts
+++ b/tests/e2e/tests.e2e.ts
@@ -61,10 +61,16 @@ describe("DateTimePicker", () => {
});
it("Should verify demo title", async () => {
- const title = await driver.findElementByText("DateTimePicker Demo NG", SearchOptions.exact);
+ const title = await driver.findElementByText("DateTimePicker Demo", SearchOptions.contains);
expect(title).to.exist;
});
+ it("Should expand date picker field examples", async () => {
+ const dateFieldTitle = await driver.findElementByText("DatePickerField", SearchOptions.contains);
+ expect(dateFieldTitle).to.exist;
+ await dateFieldTitle.click();
+ });
+
it("Should select date and verify value of picker field", async () => {
const selectDateField = await driver.findElementByText("select date", SearchOptions.contains);
await selectDateField.click();
@@ -74,15 +80,6 @@ describe("DateTimePicker", () => {
expect(dateSelected).to.exist;
});
- it("Should select time and verify value of picker field", async () => {
- const selectTimeField = await driver.findElementByText("select time", SearchOptions.contains);
- await selectTimeField.click();
- const timeString = await getPickerTime(driver, 12);
- await clickOkBtn(driver);
- const timeSelected = await driver.findElementByText(timeString, SearchOptions.contains);
- expect(timeSelected).to.exist;
- });
-
it("Should select date from min/max limited field", async () => {
const minMaxDatePicker = await driver.findElementByText("tap to select", SearchOptions.contains);
await minMaxDatePicker.click();
@@ -93,22 +90,6 @@ describe("DateTimePicker", () => {
expect(dateSelected).to.exist;
});
- it("Should open 12h time format and verify wheelers values", async () => {
- const twelveHourFormat = await driver.findElementByText("4:00 PM", SearchOptions.contains);
- await twelveHourFormat.click();
- const timeString = await getPickerTime(driver, 12);
- await clickOkBtn(driver);
- expect(timeString).to.equal("4:00 PM");
- });
-
- it("Should open 24h format and verify wheeler value", async () => {
- const twentyFourFormat = await scrollToElement(driver, "16:00", Direction.down);
- await twentyFourFormat.click();
- const timeString = await getPickerTime(driver, 24);
- await clickOkBtn(driver);
- expect(timeString).to.equal("16:00");
- });
-
it("Should verify modified texts field for date picker", async () => {
await scrollToElement(driver, "preferred locale: en_US", Direction.down);
const pickers = await driver.findElementsByText("tap to choose");
@@ -126,23 +107,8 @@ describe("DateTimePicker", () => {
expect(dateString).to.exist;
});
- it("Should verify modified texts field for time picker", async () => {
- const datePicker = await driver.findElementByText("tap to choose");
- await datePicker.click();
- const time = await getPickerTime(driver, 12);
- const approveBtn = await driver.findElementByText("Approve", SearchOptions.contains);
- const rejectBtn = await driver.findElementByText("Reject", SearchOptions.contains);
- const title = await driver.findElementByText("Confirm predefined time selection", SearchOptions.contains);
- expect(approveBtn).to.exist;
- expect(rejectBtn).to.exist;
- expect(title).to.exist;
- await approveBtn.click();
- const dateString = await driver.findElementByText(time);
- expect(dateString).to.exist;
- });
-
it("Should select date from de_De locale picker and verify format", async () => {
- await scrollToElement(driver, "zeit wählen", Direction.down);
+ await scrollToElement(driver, "datum auswählen", Direction.down);
const deLocale = await driver.findElementByText("preferred locale: de_DE");
expect(deLocale).to.exist;
const datePicker = await driver.findElementByText("datum auswählen", SearchOptions.contains);
@@ -178,31 +144,7 @@ describe("DateTimePicker", () => {
const dateString = day + "." + monthString + "." + year;
console.log(dateString);
const dateField = await driver.findElementByText(dateString);
- expect(dateString).to.exist;
- });
-
- it("Should select time from de_DE locale picker and verify format", async () => {
- const timePicker = await driver.findElementByText("zeit wählen", SearchOptions.contains);
- await timePicker.click();
- const time = await getPickerTime(driver, 24);
- let acceptBtn;
- let rejectBtn;
- if(driver.isAndroid){
- let buttons = await driver.findElementsByClassName("android.widget.Button");
- acceptBtn = buttons[5];
- rejectBtn = buttons[4];
- }
- else{
- acceptBtn = await driver.findElementByText("Bestätigen", SearchOptions.exact);
- rejectBtn = await driver.findElementByText("Stornieren", SearchOptions.exact);
- }
- const title = await driver.findElementByText("Zeit wählen", SearchOptions.exact);
- expect(acceptBtn).to.exist;
- expect(rejectBtn).to.exist;
- expect(title).to.exist;
- await acceptBtn.click();
- const dateField = await driver.findElementByText(time);
- expect(time).to.exist;
+ expect(dateField).to.exist;
});
it("Should scroll to custom format and verify values", async () => {
@@ -211,26 +153,29 @@ describe("DateTimePicker", () => {
expect(customFromatLabel).to.exist;
const customFormatDate = await driver.findElementByText("date: 24 February 2019", SearchOptions.exact);
expect(customFormatDate).to.exist;
- const customFormatTime = await driver.findElementByText("time: 01:00", SearchOptions.exact);
- expect(customFormatTime).to.exist;
+ });
+
+ it("Should scroll to css styled DatePicker and verify picker style", async () => {
+ let cssPickers = await driver.findElementsByText("Feb 24, 2019", SearchOptions.exact);
+ await cssPickers[cssPickers.length - 1].click();
+ await getPickerDate(driver);
+ await driver.compareScreen("cssDatePicker");
+ await clickOkBtn(driver);
});
it("Should scroll to binding example and verify picker and label values", async () => {
- await scrollToElement(driver, "css applied", Direction.down);
+ await scrollToElement(driver, "TimePickerField", Direction.down);
const bindingLabel = await driver.findElementByText("binding", SearchOptions.exact);
expect(bindingLabel).to.exist;
let selector = driver.isAndroid ? "android.widget.EditText" : "XCUIElementTypeTextField"
let fields = await driver.findElementsByClassName(selector);
- let timeField;
let dateField;
if(driver.isAndroid){
- timeField = fields[2];
- dateField = fields[1];
+ dateField = fields[3];
}
else{
- let index = fields.length - 3;
+ let index = fields.length;
console.log("index: " + index);
- timeField = fields[index];
dateField = fields[index - 1];
}
await dateField.click();
@@ -243,52 +188,133 @@ describe("DateTimePicker", () => {
let bindingDate = await driver.findElementByText(dateLabel, SearchOptions.contains);
});
- it("Should scroll to css styled DatePicker and verify picker style", async () => {
- await scrollToElement(driver, "tap to select time", Direction.down);
- let cssPickers = await driver.findElementsByText("Feb 24, 2019", SearchOptions.exact);
- await cssPickers[cssPickers.length - 1].click();
- await getPickerDate(driver);
- await driver.compareScreen("cssDatePicker");
+ it("Should expand time picker field examples", async () => {
+ const timeFieldTitle = await driver.findElementByText("TimePickerField", SearchOptions.contains);
+ expect(timeFieldTitle).to.exist;
+ await timeFieldTitle.click();
+ });
+
+ it("Should select time and verify value of picker field", async () => {
+ const selectTimeField = await driver.findElementByText("select time", SearchOptions.contains);
+ await selectTimeField.click();
+ const timeString = await getPickerTime(driver, 12);
await clickOkBtn(driver);
+ const timeSelected = await driver.findElementByText(timeString, SearchOptions.contains);
+ expect(timeSelected).to.exist;
});
- it("Should scroll to css styled TimePicker and verify picker style", async () => {
- const cssPickers = await driver.findElementsByText("1:00 AM", SearchOptions.exact);
- await cssPickers[cssPickers.length - 1].click();
- await getPickerTime(driver, 12);
- await driver.compareScreen("cssTimePicker");
+ it("Should open 12h time format and verify wheelers values", async () => {
+ const twelveHourFormat = await driver.findElementByText("4:00 PM", SearchOptions.contains);
+ await twelveHourFormat.click();
+ const timeString = await getPickerTime(driver, 12);
await clickOkBtn(driver);
+ expect(timeString).to.equal("4:00 PM");
});
- it("Should tap button to select date and verify button text", async () => {
- let dateButton = await driver.findElementByText("tap to select date", SearchOptions.contains);
- await dateButton.click();
- const date = await getPickerDate(driver);
+ it("Should open 24h format and verify wheeler value", async () => {
+ const twentyFourFormat = await scrollToElement(driver, "16:00", Direction.down);
+ await twentyFourFormat.click();
+ const timeString = await getPickerTime(driver, 24);
await clickOkBtn(driver);
- const pickerDate = new Date(date);
- let day = pickerDate.getDate();
- let dayString = day.toString();
- if(day < 10){
- dayString = "0" + day.toString();
- }
- let month = pickerDate.getMonth() + 1;
- let monthString = month.toString();
- if(month < 10){
- monthString = "0" + month.toString();
- }
- let year = pickerDate.getFullYear();
- const dateString = dayString + "." + monthString+ "." + year;
- console.log(dateString);
- const dateField = await driver.findElementByText(dateString);
+ expect(timeString).to.equal("16:00");
+ });
+
+ it("Should verify modified texts field for time picker", async () => {
+ await scrollToElement(driver, "tap to choose", Direction.down);
+ const datePicker = await driver.findElementByText("tap to choose");
+ await datePicker.click();
+ const time = await getPickerTime(driver, 12);
+ const approveBtn = await driver.findElementByText("Approve", SearchOptions.contains);
+ const rejectBtn = await driver.findElementByText("Reject", SearchOptions.contains);
+ const title = await driver.findElementByText("Confirm predefined time selection", SearchOptions.contains);
+ expect(approveBtn).to.exist;
+ expect(rejectBtn).to.exist;
+ expect(title).to.exist;
+ await approveBtn.click();
+ const dateString = await driver.findElementByText(time);
expect(dateString).to.exist;
- })
+ });
- it("Should tap button to select time and verify button text", async () => {
- let timeButton = await driver.findElementByText("tap to select time", SearchOptions.contains);
- await timeButton.click();
+ it("Should select time from de_DE locale picker and verify format", async () => {
+ await scrollToElement(driver, "zeit wählen", Direction.down);
+ const timePicker = await driver.findElementByText("zeit wählen", SearchOptions.contains);
+ await timePicker.click();
const time = await getPickerTime(driver, 24);
+ let acceptBtn;
+ let rejectBtn;
+ if(driver.isAndroid){
+ let buttons = await driver.findElementsByClassName("android.widget.Button");
+ acceptBtn = buttons[buttons.length - 1];
+ rejectBtn = buttons[buttons.length - 2];
+ }
+ else{
+ acceptBtn = await driver.findElementByText("Bestätigen", SearchOptions.exact);
+ rejectBtn = await driver.findElementByText("Stornieren", SearchOptions.exact);
+ }
+ const title = await driver.findElementByText("Zeit wählen", SearchOptions.exact);
+ expect(acceptBtn).to.exist;
+ expect(rejectBtn).to.exist;
+ expect(title).to.exist;
+ await acceptBtn.click();
+ const dateField = await driver.findElementByText(time, SearchOptions.contains);
+ expect(time).to.exist;
+ });
+
+ it("Should scroll to custom format and verify values", async () => {
+ await scrollToElement(driver, "binding", Direction.down);
+ const customFromatLabel = await driver.findElementByText("custom format");
+ expect(customFromatLabel).to.exist;
+ const customFormatTime = await driver.findElementByText("time: 01:00", SearchOptions.exact);
+ expect(customFormatTime).to.exist;
+ });
+
+ it("Should scroll to css styled TimePicker and verify picker style", async () => {
+ const cssPickers = await driver.findElementsByText("1:00 AM", SearchOptions.exact);
+ await cssPickers[cssPickers.length - 1].click();
+ await getPickerTime(driver, 12);
+ await driver.compareScreen("cssTimePicker");
await clickOkBtn(driver);
- timeButton = await driver.findElementByText(time);
- expect(timeButton).to.exist;
});
+
+ it("Should expand custom buttons examples", async () => {
+ await scrollToElement(driver, "Custom Buttons", Direction.down);
+ const customButtonsTitle = await driver.findElementByText("Custom Buttons", SearchOptions.contains);
+ expect(customButtonsTitle).to.exist;
+ await customButtonsTitle.click();
+ });
+
+ if (process.env["Type"] === 'Angular'){
+ it("Should tap button to select date and verify button text", async () => {
+ await scrollToElement(driver, "tap to select date and time", Direction.down);
+ let dateButton = await driver.findElementByText("tap to select date", SearchOptions.contains);
+ await dateButton.click();
+ const date = await getPickerDate(driver);
+ await clickOkBtn(driver);
+ const pickerDate = new Date(date);
+ let day = pickerDate.getDate();
+ let dayString = day.toString();
+ if(day < 10){
+ dayString = "0" + day.toString();
+ }
+ let month = pickerDate.getMonth() + 1;
+ let monthString = month.toString();
+ if(month < 10){
+ monthString = "0" + month.toString();
+ }
+ let year = pickerDate.getFullYear();
+ const dateString = dayString + "." + monthString+ "." + year;
+ console.log(dateString);
+ const dateField = await driver.findElementByText(dateString);
+ expect(dateField).to.exist;
+ })
+
+ it("Should tap button to select time and verify button text", async () => {
+ let timeButton = await driver.findElementByText("tap to select time", SearchOptions.contains);
+ await timeButton.click();
+ const time = await getPickerTime(driver, 24);
+ await clickOkBtn(driver);
+ timeButton = await driver.findElementByText(time);
+ expect(timeButton).to.exist;
+ });
+ }
});
\ No newline at end of file
diff --git a/demo-angular/e2e/tsconfig.json b/tests/e2e/tsconfig.json
similarity index 91%
rename from demo-angular/e2e/tsconfig.json
rename to tests/e2e/tsconfig.json
index 4aa39f6..2b7aa4b 100644
--- a/demo-angular/e2e/tsconfig.json
+++ b/tests/e2e/tsconfig.json
@@ -8,7 +8,8 @@
"sourceMap": true,
"types": [
"mocha",
- "chai"
+ "chai",
+ "node"
],
"lib": [
"es2015",
diff --git a/tests/package.json b/tests/package.json
new file mode 100644
index 0000000..a8dfbcc
--- /dev/null
+++ b/tests/package.json
@@ -0,0 +1,21 @@
+{
+ "devDependencies": {
+ "@types/chai": "^4.1.3",
+ "@types/mocha": "^5.2.0",
+ "@types/node": "^10.1.2",
+ "babel-loader": "~8.0.0",
+ "chai": "~4.1.2",
+ "chai-as-promised": "~7.1.1",
+ "karma": "^2.0.2",
+ "karma-nativescript-launcher": "^0.4.0",
+ "mocha": "^3.3.0",
+ "mocha-junit-reporter": "^1.18.0",
+ "mocha-multi": "1.1.0",
+ "mochawesome": "^3.1.1",
+ "nativescript-dev-appium": "~5.2.0",
+ "typescript": "~3.5.3"
+ },
+ "scripts": {
+ "e2e": "tsc -p e2e && mocha --opts ./e2e/config/mocha.opts"
+ }
+ }