diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js index b20a484d3f..a66465147d 100644 --- a/src/datepicker/datepicker.js +++ b/src/datepicker/datepicker.js @@ -539,7 +539,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst closeOnDateSelection: true, appendToBody: false, showButtonBar: true, - onOpenFocus: true + onOpenFocus: true, + altInputFormats: [] }) .controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', @@ -549,7 +550,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi isHtml5DateInput = false; var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus, datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, - ngModel, $popup; + ngModel, $popup, altInputFormats; scope.watchData = {}; @@ -560,6 +561,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus; datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl; datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl; + altInputFormats = angular.isDefined(attrs.altInputFormats) ? scope.$parent.$eval(attrs.altInputFormats) : datepickerPopupConfig.altInputFormats; scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; @@ -811,6 +813,14 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi if (angular.isString(viewValue)) { var date = dateParser.parse(viewValue, dateFormat, scope.date); + if (isNaN(date)) { + for (var i = 0; i < altInputFormats.length; i++) { + date = dateParser.parse(viewValue, altInputFormats[i], scope.date); + if (!isNaN(date)) { + break; + } + } + } if (isNaN(date)) { return undefined; } @@ -842,6 +852,14 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi if (angular.isString(value)) { var date = dateParser.parse(value, dateFormat); + if (isNaN(date)) { + for (var i = 0; i < altInputFormats.length; i++) { + date = dateParser.parse(value, altInputFormats[i]); + if (!isNaN(date)) { + break; + } + } + } return !isNaN(date); } diff --git a/src/datepicker/docs/demo.html b/src/datepicker/docs/demo.html index 7414f1847f..c97f00a971 100644 --- a/src/datepicker/docs/demo.html +++ b/src/datepicker/docs/demo.html @@ -22,7 +22,7 @@

Popup

- + @@ -40,7 +40,7 @@

Popup

- +
diff --git a/src/datepicker/docs/demo.js b/src/datepicker/docs/demo.js index 590b759fbb..aac7f0b2d3 100644 --- a/src/datepicker/docs/demo.js +++ b/src/datepicker/docs/demo.js @@ -39,6 +39,7 @@ angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function ($ $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate']; $scope.format = $scope.formats[0]; + $scope.altInputFormats = ['M!/d!/yyyy']; $scope.popup1 = { opened: false diff --git a/src/datepicker/docs/readme.md b/src/datepicker/docs/readme.md index 41062109df..5d020916f9 100644 --- a/src/datepicker/docs/readme.md +++ b/src/datepicker/docs/readme.md @@ -144,6 +144,10 @@ Options for the uib-datepicker must be passed as JSON using the `datepicker-opti _(Default: `yyyy-MM-dd`)_ - The format for displayed dates. This string can take string literals by surrounding the value with single quotes, i.e. `yyyy-MM-dd h 'o\'clock'`. + * `alt-input-formats` + _(Default: `[]`)_: + A list of alternate formats acceptable for manual entry. + ### Keyboard support ### Depending on datepicker's current mode, the date may refer either to day, month or year. Accordingly, the term view refers either to a month, year or year range. diff --git a/src/datepicker/test/datepicker.spec.js b/src/datepicker/test/datepicker.spec.js index e9384a5d4a..972bb57a8c 100644 --- a/src/datepicker/test/datepicker.spec.js +++ b/src/datepicker/test/datepicker.spec.js @@ -2339,6 +2339,51 @@ describe('datepicker', function() { }); }); + describe('altInputFormats', function() { + describe('datepickerPopupConfig.altInputFormats', function() { + var originalConfig = {}; + beforeEach(inject(function(uibDatepickerPopupConfig) { + angular.extend(originalConfig, uibDatepickerPopupConfig); + uibDatepickerPopupConfig.datepickerPopup = 'MM-dd-yyyy'; + uibDatepickerPopupConfig.altInputFormats = ['M!/d!/yyyy']; + + var wrapElement = $compile('
')($rootScope); + $rootScope.$digest(); + assignElements(wrapElement); + })); + + afterEach(inject(function(uibDatepickerPopupConfig) { + // return it to the original state + angular.extend(uibDatepickerPopupConfig, originalConfig); + })); + + it('changes date format', function() { + changeInputValueTo(inputEl, '11/8/1980'); + + expect($rootScope.date.getFullYear()).toEqual(1980); + expect($rootScope.date.getMonth()).toEqual(10); + expect($rootScope.date.getDate()).toEqual(8); + }); + }); + + describe('attribute `alt-input-formats`', function() { + beforeEach(function() { + $rootScope.date = new Date('November 9, 1980'); + var wrapElement = $compile('
')($rootScope); + $rootScope.$digest(); + assignElements(wrapElement); + }); + + it('should accept alternate input formats', function() { + changeInputValueTo(inputEl, '11/8/1980'); + + expect($rootScope.date.getFullYear()).toEqual(1980); + expect($rootScope.date.getMonth()).toEqual(10); + expect($rootScope.date.getDate()).toEqual(8); + }); + }); + }); + describe('pass through attributes', function() { var wrapElement; describe('formatting', function() {