diff --git a/README.md b/README.md index 8404294..15a2699 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![npm](https://img.shields.io/npm/dm/nativescript-datetimepicker.svg)](https://www.npmjs.com/package/nativescript-datetimepicker) [![Build Status](https://travis-ci.org/NativeScript/nativescript-datetimepicker.svg?branch=master)](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 +12,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 +33,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 +60,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 +72,7 @@ Then you will be able to decrare the fields in the template of your component: ```html + ``` ## Features @@ -78,23 +82,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 +106,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 +114,50 @@ You can use css to style the `DatePickerField` and the `TimePickerField`. The fi DatePickerField with CSS applied on iOS (left) and Android (right) -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 @@ -125,7 +168,7 @@ Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pick | `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). | +| `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) | | `pickerTitle` | Text that will be displayed as title of the picker, default is undefined. | @@ -144,6 +187,26 @@ Internally `DatePickerField` and `TimePickerField` call `DateTimePicker`'s `pick | `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. | +| `minDate` | The minimum date the date component can select. | +| `maxDate` | The maximum date the time component can select. | +| `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. | +| `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). | +| `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 +224,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/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 index eec1d1e..fbd4bef 100644 Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png and b/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssDatePicker.png 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 index eaebbec..8252547 100644 Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png and b/demo-angular/e2e/resources/images/datetimepicker-ng-android/Android GoogleAPI Emulator/cssTimePicker.png 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 index 3a5c87f..2c2e8ef 100644 Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png and b/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssDatePicker.png 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 index 8eba30d..900abe4 100644 Binary files a/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png and b/demo-angular/e2e/resources/images/datetimepicker-ng-ios/iPhone X/cssTimePicker.png differ diff --git a/demo-angular/e2e/tests.e2e.ts b/demo-angular/e2e/tests.e2e.ts index 7acbc59..8bd225e 100644 --- a/demo-angular/e2e/tests.e2e.ts +++ b/demo-angular/e2e/tests.e2e.ts @@ -65,6 +65,12 @@ describe("DateTimePicker", () => { 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); @@ -181,56 +147,35 @@ describe("DateTimePicker", () => { 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; - }); - 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 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,13 +188,84 @@ 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 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 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 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[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; + }); + + 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 () => { @@ -260,7 +276,15 @@ describe("DateTimePicker", () => { await clickOkBtn(driver); }); + 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(); + }); + 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); 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..55f8206 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") 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/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 @@ - + -