-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Feat input timeformat #16584
Feat input timeformat #16584
Changes from 4 commits
d6e7920
a676fa5
0083aef
1dea038
11072f6
a528a70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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} `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. | ||
* @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} `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. | ||
|
@@ -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; | ||
|
||
|
@@ -1514,11 +1525,13 @@ 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); | ||
|
||
return formatter(value, timezone); | ||
} else { | ||
previousDate = null; | ||
previousTimezone = null; | ||
|
@@ -1573,6 +1586,25 @@ function createDateInputType(type, regexp, parseDate, format) { | |
} | ||
return parsedDate; | ||
} | ||
|
||
function formatter(value, timezone) { | ||
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); | ||
} | ||
} | ||
|
||
var formatted = $filter('date')(value, targetFormat, timezone); | ||
|
||
if (isTimeType && ctrl.$options.getOption('timeStripEmptySeconds')) { | ||
formatted = formatted.replace(/(:00)?(\.000)?$/, ''); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Since you are not using the captured groups, it is better to use |
||
} | ||
|
||
return formatted; | ||
} | ||
}; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -406,12 +406,6 @@ defaultModelOptions = new ModelOptions({ | |
* </example> | ||
* | ||
* | ||
* ## 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 `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. | ||
* | ||
<example name="ngModelOptions-time-format" module="timeExample"> | ||
<file name="index.html"> | ||
<time-example></time-example> | ||
</file> | ||
<file name="script.js"> | ||
angular.module('timeExample', []) | ||
.component('timeExample', { | ||
templateUrl: 'timeExample.html', | ||
controller: function() { | ||
this.time = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this need to be an object? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, but it's good practice ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disagrees, but not strongly enough to be bothered 😛 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (it is only good practice if you are working directly with the scope - in this case you already have an object on the scope |
||
value: new Date(1970, 0, 1, 14, 57, 0) | ||
}; | ||
|
||
this.options = { | ||
timeSecondsFormat: 'ss', | ||
timeStripEmptySeconds: true | ||
}; | ||
|
||
this.optionChange = function() { | ||
this.timeForm.timeFormatted.$overrideModelOptions(this.options); | ||
this.time.value = new Date(this.time.value); | ||
}; | ||
} | ||
}); | ||
</file> | ||
<file name="timeExample.html"> | ||
<form name="$ctrl.timeForm"> | ||
<strong>Default</strong>: | ||
<input type="time" ng-model="$ctrl.time.value" step="any" /><br> | ||
<strong>With options</strong>: | ||
<input type="time" name="timeFormatted" ng-model="$ctrl.time.value" step="any" ng-model-options="$ctrl.options" /> | ||
<br> | ||
|
||
Options:<br> | ||
<code>timeSecondsFormat</code>: | ||
<input | ||
type="text" | ||
ng-model="$ctrl.options.timeSecondsFormat" | ||
ng-change="$ctrl.optionChange()"> | ||
<br> | ||
<code>timeStripEmptySeconds</code>: | ||
<input | ||
type="checkbox" | ||
ng-model="$ctrl.options.timeStripEmptySeconds" | ||
ng-change="$ctrl.optionChange()"> | ||
</form> | ||
</file> | ||
* </example> | ||
* | ||
* @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 | ||
* `<input type="date" />`, `<input type="time" />`, ... . It understands UTC/GMT and the | ||
* continental US time zone abbreviations, but for general use, use a time zone offset, for | ||
|
@@ -465,6 +527,24 @@ 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. | ||
* | ||
* - `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 | ||
* 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 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}. | ||
* | ||
*/ | ||
var ngModelOptionsDirective = function() { | ||
NgModelOptionsController.$inject = ['$attrs', '$scope']; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is ugly but I couldn't be bothered to use a regex :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is ugly and would be simpler with: