From d6e7920c589d0e1fd776ea9e99491fd764dde1d0 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 25 May 2018 18:47:56 +0200 Subject: [PATCH 1/6] wip: time format --- src/ng/directive/input.js | 13 ++++- test/ng/directive/inputSpec.js | 95 ++++++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 2eb4b0d7227d..72a662a0990a 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1514,11 +1514,22 @@ function createDateInputType(type, regexp, parseDate, format) { if (isValidDate(value)) { previousDate = value; var timezone = ctrl.$options.getOption('timezone'); + if (timezone) { previousTimezone = timezone; previousDate = convertTimezoneToLocal(previousDate, timezone, true); } - return $filter('date')(value, format, timezone); + + var adjustedFormat = (type === 'time' && ctrl.$options.getOption('timeFormat')) || format; + + var formatted = $filter('date')(value, adjustedFormat, timezone); + + console.log('formatted', formatted); + if (ctrl.$options.getOption('timeRemoveZeroes')) { + formatted = formatted.replace(/(:00)?(\.000)?$/, ''); + } + + return formatted; } else { previousDate = null; previousTimezone = null; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index fdb5af255624..83fd2ad633e5 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -2,7 +2,7 @@ /* globals generateInputCompilerHelper: false */ -describe('input', function() { +fdescribe('input', function() { var helper = {}, $compile, $rootScope, $browser, $sniffer; // UA sniffing to exclude Edge from some date input tests @@ -1581,7 +1581,7 @@ describe('input', function() { }); - describe('time', function() { + fdescribe('time', function() { it('should throw if model is not a Date object', function() { var inputElm = helper.compileInput(''); @@ -1593,7 +1593,7 @@ describe('input', function() { }); - it('should set the view if the model if a valid Date object.', function() { + it('should set the view if the model is a valid Date object.', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { @@ -1623,7 +1623,7 @@ describe('input', function() { }); - it('should render as blank if null', function() { + it('should set blank if null', function() { var inputElm = helper.compileInput(''); $rootScope.$apply('test = null'); @@ -1633,7 +1633,7 @@ describe('input', function() { }); - it('should come up blank when no value specified', function() { + it('should set blank when no value specified', function() { var inputElm = helper.compileInput(''); expect(inputElm.val()).toBe(''); @@ -1644,6 +1644,91 @@ describe('input', function() { expect(inputElm.val()).toBe(''); }); + fit('should use the timeFormat specified in ngModelOptions', function() { + var inputElm = helper.compileInput(''); + + var ctrl = inputElm.controller('ngModel'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + expect(inputElm.val()).toBe('15:41'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + expect(inputElm.val()).toBe('15:41'); + + ctrl.$overrideModelOptions({timeFormat: 'HH:mm:s'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); + }); + expect(inputElm.val()).toBe('15:41:5'); + + ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); + }); + expect(inputElm.val()).toBe('15:41:05'); + + ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss.sss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); + }); + expect(inputElm.val()).toBe('15:41:50.050'); + + }); + + + it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('15:41:50.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('15:41:00.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 0); + }); + + expect(inputElm.val()).toBe('15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 0); + }); + + expect(inputElm.val()).toBe('15:41'); + }); + + + it('should apply timeRemoveZeroes after timeFormat', function() { + // var inputElm = helper.compileInput(''); + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('15:41'); + }); + it('should parse empty string to null', function() { var inputElm = helper.compileInput(''); From a676fa5e9f3917b37b3b499c87c483098ebf94c6 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 30 May 2018 20:24:33 +0200 Subject: [PATCH 2/6] add option to datetime-local and add docs --- src/ng/directive/input.js | 40 ++++++++--- src/ng/directive/ngModelOptions.js | 91 ++++++++++++++++++++++-- test/ng/directive/inputSpec.js | 110 +++++++++++++++++++++++++---- 3 files changed, 208 insertions(+), 33 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 72a662a0990a..9904854471d3 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -255,6 +255,10 @@ var inputType = { * The timezone to be used to read/write the `Date` instance in the model can be defined using * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. * + * The format of the displayed time can be adjusted with the + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeFormat` and + * `timeStripEmptySeconds`. + * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. @@ -356,7 +360,12 @@ var inputType = { * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. * * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions}. By default, + * this is the timezone of the browser. + * + * The format of the displayed time can be adjusted with the + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeFormat` and + * `timeStripEmptySeconds`. * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. @@ -1491,6 +1500,8 @@ function createDateInputType(type, regexp, parseDate, format) { return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { badInputChecker(scope, element, attr, ctrl, type); baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var isTimeType = type === 'time' || type === 'datetimelocal'; var previousDate; var previousTimezone; @@ -1520,16 +1531,7 @@ function createDateInputType(type, regexp, parseDate, format) { previousDate = convertTimezoneToLocal(previousDate, timezone, true); } - var adjustedFormat = (type === 'time' && ctrl.$options.getOption('timeFormat')) || format; - - var formatted = $filter('date')(value, adjustedFormat, timezone); - - console.log('formatted', formatted); - if (ctrl.$options.getOption('timeRemoveZeroes')) { - formatted = formatted.replace(/(:00)?(\.000)?$/, ''); - } - - return formatted; + return formatter(value, timezone); } else { previousDate = null; previousTimezone = null; @@ -1584,6 +1586,22 @@ function createDateInputType(type, regexp, parseDate, format) { } return parsedDate; } + + function formatter(value, timezone) { + var targetFormat = format; + + if (isTimeType && isString(ctrl.$options.getOption('timeFormat'))) { + targetFormat = ctrl.$options.getOption('timeFormat'); + } + + var formatted = $filter('date')(value, targetFormat, timezone); + + if (isTimeType && ctrl.$options.getOption('timeStripEmptySeconds')) { + formatted = formatted.replace(/(:00)?(\.000)?$/, ''); + } + + return formatted; + } }; } diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index 62408d2ea84a..6a13328f00e1 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -406,12 +406,6 @@ defaultModelOptions = new ModelOptions({ * * * - * ## Specifying timezones - * - * You can specify the timezone that date/time input directives expect by providing its name in the - * `timezone` property. - * - * * ## Programmatically changing options * * The `ngModelOptions` expression is only evaluated once when the directive is linked; it is not @@ -423,8 +417,72 @@ defaultModelOptions = new ModelOptions({ * Default events, extra triggers, and catch-all debounce values}. * * + * ## Specifying timezones + * + * You can specify the timezone that date/time input directives expect by providing its name in the + * `timezone` property. + * + * + * ## Formatting the value of `time` and `datetime-local` + * + * With the options `timeFormat` and `timeStripEmptySeconds` it is possible to adjust the value + * that is displayed in the browser control. Note that browsers may apply their own formatting + * in the user interface. + * + + + + + + angular.module('timeExample', []) + .component('timeExample', { + templateUrl: 'timeExample.html', + controller: function() { + this.time = { + value: new Date(1970, 0, 1, 14, 57, 30) + }; + + this.options = { + timeFormat: 'HH:mm:ss', + timeStripEmptySeconds: true + }; + + this.optionChange = function() { + this.timeForm.timeFormatted.$overrideModelOptions(this.options); + this.time.value = new Date(this.time.value.getTime()); + }; + } + }); + + +
+ Default: +
+ With options: + +
+ + Options:
+ timeFormat: + +
+ timeStripEmptySeconds: + +
+
+ *
+ * * @param {Object} ngModelOptions options to apply to {@link ngModel} directives on this element and - * and its descendents. Valid keys are: + * and its descendents. + * + * **General options**: + * * - `updateOn`: string specifying which event should the input be bound to. You can set several * events using an space delimited list. There is a special event called `default` that * matches the default events belonging to the control. These are the events that are bound to @@ -457,6 +515,10 @@ defaultModelOptions = new ModelOptions({ * not validate correctly instead of the default behavior of setting the model to undefined. * - `getterSetter`: boolean value which determines whether or not to treat functions bound to * `ngModel` as getters/setters. + * + * + * **Input-type specific options**: + * * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for * ``, ``, ... . It understands UTC/GMT and the * continental US time zone abbreviations, but for general use, use a time zone offset, for @@ -465,6 +527,21 @@ defaultModelOptions = new ModelOptions({ * Note that changing the timezone will have no effect on the current date, and is only applied after * the next input / model change. * + * - `timeFormat`: Defines if the `time` and `datetime-local` types should show seconds and + * milliseconds. The option follows the format string of {@link date date filter}. + * By default, the options is `undefined` which is equal to + * `HH:mm:ss.sss` (shows hours, minutes, seconds and milliseconds). The other options are + * `HH:mm:ss` (strips milliseconds), and `HH:mm`, which strips both seconds and milliseconds. + * Note that browsers that support `time` and `datetime-local` may show the value differently + * in the user interface. + * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. + * + * - `timeStripEmptySeconds`: Defines if the `time` and `datetime-local` types should trim the + * seconds and milliseconds if they are zero. This option is useful for browsers that either don't + * have a special interface for `time` and `date` input types, or those that don't hide seconds + * and milliseconds if they are empty. This option is applied after `timeFormat`. + * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. + * */ var ngModelOptionsDirective = function() { NgModelOptionsController.$inject = ['$attrs', '$scope']; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 83fd2ad633e5..b57068339d31 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -2,7 +2,7 @@ /* globals generateInputCompilerHelper: false */ -fdescribe('input', function() { +describe('input', function() { var helper = {}, $compile, $rootScope, $browser, $sniffer; // UA sniffing to exclude Edge from some date input tests @@ -1384,6 +1384,89 @@ fdescribe('input', function() { expect($rootScope.form.alias.$error.datetimelocal).toBeTruthy(); }); + it('should use the timeFormat specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); + + var ctrl = inputElm.controller('ngModel'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41'); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41'); + + ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41:05'); + + ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss.sss'}); + + $rootScope.$apply(function() { + $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); + }); + expect(inputElm.val()).toBe('1970-01-01T15:41:50.050'); + + }); + + + it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:50.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:00.500'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 0); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 0); + }); + + expect(inputElm.val()).toBe('1970-01-01T15:41'); + }); + + + it('should apply timeStripEmptySeconds after timeFormat', function() { + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); + }); + + expect(inputElm.val()).toBe('15:41:50'); + + $rootScope.$apply(function() { + $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); + }); + + expect(inputElm.val()).toBe('15:41'); + }); + describe('min', function() { var inputElm; beforeEach(function() { @@ -1581,7 +1664,7 @@ fdescribe('input', function() { }); - fdescribe('time', function() { + describe('time', function() { it('should throw if model is not a Date object', function() { var inputElm = helper.compileInput(''); @@ -1604,7 +1687,7 @@ fdescribe('input', function() { }); - it('should set the model undefined if the view is invalid', function() { + it('should set the model to undefined if the view is invalid', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { @@ -1644,8 +1727,10 @@ fdescribe('input', function() { expect(inputElm.val()).toBe(''); }); - fit('should use the timeFormat specified in ngModelOptions', function() { - var inputElm = helper.compileInput(''); + it('should use the timeFormat specified in ngModelOptions', function() { + var inputElm = helper.compileInput( + '' + ); var ctrl = inputElm.controller('ngModel'); @@ -1659,13 +1744,6 @@ fdescribe('input', function() { }); expect(inputElm.val()).toBe('15:41'); - ctrl.$overrideModelOptions({timeFormat: 'HH:mm:s'}); - - $rootScope.$apply(function() { - $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); - }); - expect(inputElm.val()).toBe('15:41:5'); - ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss'}); $rootScope.$apply(function() { @@ -1684,7 +1762,9 @@ fdescribe('input', function() { it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { - var inputElm = helper.compileInput(''); + var inputElm = helper.compileInput( + '' + ); $rootScope.$apply(function() { $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); @@ -1712,9 +1792,9 @@ fdescribe('input', function() { }); - it('should apply timeRemoveZeroes after timeFormat', function() { + it('should apply timeStripEmptySeconds after timeFormat', function() { // var inputElm = helper.compileInput(''); - var inputElm = helper.compileInput(''); + var inputElm = helper.compileInput(''); $rootScope.$apply(function() { $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); From 0083aefe915d1d56019c54bb58c113be14f3d553 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 30 May 2018 21:10:29 +0200 Subject: [PATCH 3/6] change to timeSecondsFormat --- src/ng/directive/input.js | 7 +++++-- src/ng/directive/ngModelOptions.js | 8 ++++---- test/ng/directive/inputSpec.js | 31 +++++++++++++++--------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 9904854471d3..2e35c2342a07 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1590,8 +1590,11 @@ function createDateInputType(type, regexp, parseDate, format) { function formatter(value, timezone) { var targetFormat = format; - if (isTimeType && isString(ctrl.$options.getOption('timeFormat'))) { - targetFormat = ctrl.$options.getOption('timeFormat'); + if (isTimeType && isString(ctrl.$options.getOption('timeSecondsFormat'))) { + targetFormat = format.replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat')); + if (targetFormat[targetFormat.length - 1] === ':') { + targetFormat = targetFormat.slice(0, -1); + } } var formatted = $filter('date')(value, targetFormat, timezone); diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index 6a13328f00e1..7ba2839993b2 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -439,11 +439,11 @@ defaultModelOptions = new ModelOptions({ templateUrl: 'timeExample.html', controller: function() { this.time = { - value: new Date(1970, 0, 1, 14, 57, 30) + value: new Date(1970, 0, 1, 14, 57, 0) }; this.options = { - timeFormat: 'HH:mm:ss', + timeSecondsFormat: 'ss', timeStripEmptySeconds: true }; @@ -463,10 +463,10 @@ defaultModelOptions = new ModelOptions({
Options:
- timeFormat: + timeSecondsFormat:
timeStripEmptySeconds: diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index b57068339d31..9af830ec14fc 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1384,9 +1384,9 @@ describe('input', function() { expect($rootScope.form.alias.$error.datetimelocal).toBeTruthy(); }); - it('should use the timeFormat specified in ngModelOptions', function() { + it('should use the timeSecondsFormat specified in ngModelOptions', function() { var inputElm = helper.compileInput( - '' + '' ); var ctrl = inputElm.controller('ngModel'); @@ -1401,14 +1401,14 @@ describe('input', function() { }); expect(inputElm.val()).toBe('1970-01-01T15:41'); - ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss'}); + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss'}); $rootScope.$apply(function() { $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); }); expect(inputElm.val()).toBe('1970-01-01T15:41:05'); - ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss.sss'}); + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss.sss'}); $rootScope.$apply(function() { $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); @@ -1449,22 +1449,22 @@ describe('input', function() { }); - it('should apply timeStripEmptySeconds after timeFormat', function() { + it('should apply timeStripEmptySeconds after timeSecondsFormat', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); }); - expect(inputElm.val()).toBe('15:41:50'); + expect(inputElm.val()).toBe('1970-01-01T15:41:50'); $rootScope.$apply(function() { $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 0, 500); }); - expect(inputElm.val()).toBe('15:41'); + expect(inputElm.val()).toBe('1970-01-01T15:41'); }); describe('min', function() { @@ -1727,9 +1727,9 @@ describe('input', function() { expect(inputElm.val()).toBe(''); }); - it('should use the timeFormat specified in ngModelOptions', function() { + it('should use the timeSecondsFormat specified in ngModelOptions', function() { var inputElm = helper.compileInput( - '' + '' ); var ctrl = inputElm.controller('ngModel'); @@ -1744,14 +1744,14 @@ describe('input', function() { }); expect(inputElm.val()).toBe('15:41'); - ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss'}); + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss'}); $rootScope.$apply(function() { $rootScope.time = new Date(1970, 0, 1, 15, 41, 5, 500); }); expect(inputElm.val()).toBe('15:41:05'); - ctrl.$overrideModelOptions({timeFormat: 'HH:mm:ss.sss'}); + ctrl.$overrideModelOptions({timeSecondsFormat: 'ss.sss'}); $rootScope.$apply(function() { $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); @@ -1792,9 +1792,10 @@ describe('input', function() { }); - it('should apply timeStripEmptySeconds after timeFormat', function() { - // var inputElm = helper.compileInput(''); - var inputElm = helper.compileInput(''); + it('should apply timeStripEmptySeconds after timeSecondsFormat', function() { + var inputElm = helper.compileInput(''); $rootScope.$apply(function() { $rootScope.threeFortyOnePm = new Date(1970, 0, 1, 15, 41, 50, 500); From 1dea038b8e95ff61f27e8763bdec45aec581a7ab Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 1 Jun 2018 10:18:35 +0200 Subject: [PATCH 4/6] fixup! add option to datetime-local and add docs --- src/ng/directive/input.js | 8 ++++---- src/ng/directive/ngModelOptions.js | 29 ++++++++++++++++------------- test/ng/directive/inputSpec.js | 2 -- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 2e35c2342a07..303d7f2d8cae 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -256,8 +256,8 @@ var inputType = { * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. * * The format of the displayed time can be adjusted with the - * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeFormat` and - * `timeStripEmptySeconds`. + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` + * and `timeStripEmptySeconds`. * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. @@ -364,8 +364,8 @@ var inputType = { * this is the timezone of the browser. * * The format of the displayed time can be adjusted with the - * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeFormat` and - * `timeStripEmptySeconds`. + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` + * and `timeStripEmptySeconds`. * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index 7ba2839993b2..63ba040a3924 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -425,8 +425,8 @@ defaultModelOptions = new ModelOptions({ * * ## Formatting the value of `time` and `datetime-local` * - * With the options `timeFormat` and `timeStripEmptySeconds` it is possible to adjust the value - * that is displayed in the browser control. Note that browsers may apply their own formatting + * With the options `timeSecondsFormat` and `timeStripEmptySeconds` it is possible to adjust the value + * that is displayed in the control. Note that browsers may apply their own formatting * in the user interface. * @@ -449,7 +449,7 @@ defaultModelOptions = new ModelOptions({ this.optionChange = function() { this.timeForm.timeFormatted.$overrideModelOptions(this.options); - this.time.value = new Date(this.time.value.getTime()); + this.time.value = new Date(this.time.value); }; } }); @@ -527,19 +527,22 @@ defaultModelOptions = new ModelOptions({ * Note that changing the timezone will have no effect on the current date, and is only applied after * the next input / model change. * - * - `timeFormat`: Defines if the `time` and `datetime-local` types should show seconds and + * - `timeSecondsFormat`: Defines if the `time` and `datetime-local` types should show seconds and * milliseconds. The option follows the format string of {@link date date filter}. - * By default, the options is `undefined` which is equal to - * `HH:mm:ss.sss` (shows hours, minutes, seconds and milliseconds). The other options are - * `HH:mm:ss` (strips milliseconds), and `HH:mm`, which strips both seconds and milliseconds. - * Note that browsers that support `time` and `datetime-local` may show the value differently - * in the user interface. + * By default, the options is `undefined` which is equal to `ss.sss` (seconds and milliseconds). + * The other options are `ss` (strips milliseconds), and `` (empty string), which strips both + * seconds and milliseconds. + * Note that browsers that support `time` and `datetime-local` require the hour and minutes + * part of the time, and may show the value differently in the user interface. * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. * - * - `timeStripEmptySeconds`: Defines if the `time` and `datetime-local` types should trim the - * seconds and milliseconds if they are zero. This option is useful for browsers that either don't - * have a special interface for `time` and `date` input types, or those that don't hide seconds - * and milliseconds if they are empty. This option is applied after `timeFormat`. + * - `timeStripEmptySeconds`: Defines if the `time` and `datetime-local` types should strip the + * seconds and milliseconds from the formatted value if they are zero. This option is applied + * after `timeSecondsFormat`. + * This option can be used to make the formatting consistent over different browsers, as some + * browsers with support for `time` will natively hide the milliseconds and + * seconds if they are zero, but others won't, and browsers without `support` will always show + * the full string. * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. * */ diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 9af830ec14fc..627f453d1c58 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1414,7 +1414,6 @@ describe('input', function() { $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); }); expect(inputElm.val()).toBe('1970-01-01T15:41:50.050'); - }); @@ -1757,7 +1756,6 @@ describe('input', function() { $rootScope.time = new Date(1970, 0, 1, 15, 41, 50, 50); }); expect(inputElm.val()).toBe('15:41:50.050'); - }); From 11072f65087e85ad482cb1e4d6ce87df1df8d78a Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Wed, 6 Jun 2018 15:32:28 +0200 Subject: [PATCH 5/6] fixup! fixup! add option to datetime-local and add docs --- src/ng/directive/input.js | 9 ++++----- src/ng/directive/ngModelOptions.js | 10 ++++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 303d7f2d8cae..5de8d32615ed 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1591,16 +1591,15 @@ function createDateInputType(type, regexp, parseDate, format) { var targetFormat = format; if (isTimeType && isString(ctrl.$options.getOption('timeSecondsFormat'))) { - targetFormat = format.replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat')); - if (targetFormat[targetFormat.length - 1] === ':') { - targetFormat = targetFormat.slice(0, -1); - } + targetFormat = format + .replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat')) + .replace(/:$/, ''); } var formatted = $filter('date')(value, targetFormat, timezone); if (isTimeType && ctrl.$options.getOption('timeStripEmptySeconds')) { - formatted = formatted.replace(/(:00)?(\.000)?$/, ''); + formatted = formatted.replace(/(?::00)?(?:\.000)?$/, ''); } return formatted; diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index 63ba040a3924..f47021510132 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -438,9 +438,7 @@ defaultModelOptions = new ModelOptions({ .component('timeExample', { templateUrl: 'timeExample.html', controller: function() { - this.time = { - value: new Date(1970, 0, 1, 14, 57, 0) - }; + this.time = new Date(1970, 0, 1, 14, 57, 0); this.options = { timeSecondsFormat: 'ss', @@ -449,7 +447,7 @@ defaultModelOptions = new ModelOptions({ this.optionChange = function() { this.timeForm.timeFormatted.$overrideModelOptions(this.options); - this.time.value = new Date(this.time.value); + this.time = new Date(this.time); }; } }); @@ -457,9 +455,9 @@ defaultModelOptions = new ModelOptions({
Default: -
+
With options: - +
Options:
From a528a70d2da57319605dd7b5ca031dee6a7713fc Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Tue, 12 Jun 2018 22:45:44 +0200 Subject: [PATCH 6/6] fixup! wip: time format --- src/ng/directive/input.js | 6 +++--- src/ng/directive/ngModelOptions.js | 20 ++++++++++---------- test/ng/directive/inputSpec.js | 12 ++++++------ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 5de8d32615ed..bf6576f81a09 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -257,7 +257,7 @@ var inputType = { * * The format of the displayed time can be adjusted with the * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` - * and `timeStripEmptySeconds`. + * and `timeStripZeroSeconds`. * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. @@ -365,7 +365,7 @@ var inputType = { * * The format of the displayed time can be adjusted with the * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` - * and `timeStripEmptySeconds`. + * and `timeStripZeroSeconds`. * * @param {string} ngModel Assignable AngularJS expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. @@ -1598,7 +1598,7 @@ function createDateInputType(type, regexp, parseDate, format) { var formatted = $filter('date')(value, targetFormat, timezone); - if (isTimeType && ctrl.$options.getOption('timeStripEmptySeconds')) { + if (isTimeType && ctrl.$options.getOption('timeStripZeroSeconds')) { formatted = formatted.replace(/(?::00)?(?:\.000)?$/, ''); } diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index f47021510132..2a32affc76ef 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -425,7 +425,7 @@ defaultModelOptions = new ModelOptions({ * * ## Formatting the value of `time` and `datetime-local` * - * With the options `timeSecondsFormat` and `timeStripEmptySeconds` it is possible to adjust the value + * With the options `timeSecondsFormat` and `timeStripZeroSeconds` it is possible to adjust the value * that is displayed in the control. Note that browsers may apply their own formatting * in the user interface. * @@ -442,7 +442,7 @@ defaultModelOptions = new ModelOptions({ this.options = { timeSecondsFormat: 'ss', - timeStripEmptySeconds: true + timeStripZeroSeconds: true }; this.optionChange = function() { @@ -467,10 +467,10 @@ defaultModelOptions = new ModelOptions({ ng-model="$ctrl.options.timeSecondsFormat" ng-change="$ctrl.optionChange()">
- timeStripEmptySeconds: + timeStripZeroSeconds:
@@ -527,20 +527,20 @@ defaultModelOptions = new ModelOptions({ * * - `timeSecondsFormat`: Defines if the `time` and `datetime-local` types should show seconds and * milliseconds. The option follows the format string of {@link date date filter}. - * By default, the options is `undefined` which is equal to `ss.sss` (seconds and milliseconds). - * The other options are `ss` (strips milliseconds), and `` (empty string), which strips both + * By default, the options is `undefined` which is equal to `'ss.sss'` (seconds and milliseconds). + * The other options are `'ss'` (strips milliseconds), and `''` (empty string), which strips both * seconds and milliseconds. * Note that browsers that support `time` and `datetime-local` require the hour and minutes - * part of the time, and may show the value differently in the user interface. + * part of the time string, and may show the value differently in the user interface. * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. * - * - `timeStripEmptySeconds`: Defines if the `time` and `datetime-local` types should strip the + * - `timeStripZeroSeconds`: Defines if the `time` and `datetime-local` types should strip the * seconds and milliseconds from the formatted value if they are zero. This option is applied * after `timeSecondsFormat`. * This option can be used to make the formatting consistent over different browsers, as some * browsers with support for `time` will natively hide the milliseconds and - * seconds if they are zero, but others won't, and browsers without `support` will always show - * the full string. + * seconds if they are zero, but others won't, and browsers that don't implement these input + * types will always show the full string. * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. * */ diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 627f453d1c58..79b44c910170 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1419,7 +1419,7 @@ describe('input', function() { it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { var inputElm = helper.compileInput( - '' + '' ); $rootScope.$apply(function() { @@ -1448,9 +1448,9 @@ describe('input', function() { }); - it('should apply timeStripEmptySeconds after timeSecondsFormat', function() { + it('should apply timeStripZeroSeconds after timeSecondsFormat', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { @@ -1761,7 +1761,7 @@ describe('input', function() { it('should strip empty milliseconds and seconds if specified in ngModelOptions', function() { var inputElm = helper.compileInput( - '' + '' ); $rootScope.$apply(function() { @@ -1790,9 +1790,9 @@ describe('input', function() { }); - it('should apply timeStripEmptySeconds after timeSecondsFormat', function() { + it('should apply timeStripZeroSeconds after timeSecondsFormat', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() {