From 500d208b6a1d4512880bbc6bbaf57526dff5d07d Mon Sep 17 00:00:00 2001 From: Dennis Stevense Date: Tue, 3 Mar 2015 20:58:40 -0800 Subject: [PATCH] fix(datepicker): Parse date from $viewValue instead of $modelValue Allow use in conjunction with an ngModelController that has custom formatters and parsers to translate between $modelValue and $viewValue --- src/datepicker/datepicker.js | 10 +++--- src/datepicker/test/datepicker.spec.js | 46 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js index bc2354f110..9880bcac0f 100644 --- a/src/datepicker/datepicker.js +++ b/src/datepicker/datepicker.js @@ -63,8 +63,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst }; this.render = function() { - if ( ngModelCtrl.$modelValue ) { - var date = new Date( ngModelCtrl.$modelValue ), + if ( ngModelCtrl.$viewValue ) { + var date = new Date( ngModelCtrl.$viewValue ), isValid = !isNaN(date); if ( isValid ) { @@ -81,13 +81,13 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst if ( this.element ) { this._refreshView(); - var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null; + var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date))); } }; this.createDateObject = function(date, format) { - var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null; + var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; return { date: date, label: dateFilter(date, format), @@ -112,7 +112,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst $scope.select = function( date ) { if ( $scope.datepickerMode === self.minMode ) { - var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + var dt = ngModelCtrl.$viewValue ? new Date( ngModelCtrl.$viewValue ) : new Date(0, 0, 0, 0, 0, 0, 0); dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); ngModelCtrl.$setViewValue( dt ); ngModelCtrl.$render(); diff --git a/src/datepicker/test/datepicker.spec.js b/src/datepicker/test/datepicker.spec.js index b673d162da..7e6b124ead 100644 --- a/src/datepicker/test/datepicker.spec.js +++ b/src/datepicker/test/datepicker.spec.js @@ -6,6 +6,26 @@ describe('datepicker directive', function () { beforeEach(module('template/datepicker/month.html')); beforeEach(module('template/datepicker/year.html')); beforeEach(module('template/datepicker/popup.html')); + beforeEach(module(function($compileProvider) { + $compileProvider.directive('dateModel', function() { + return { + restrict: 'A', + require: 'ngModel', + link: function(scope, element, attrs, modelController) { + modelController.$formatters.push(function(object) { + return new Date(object.date); + }); + + modelController.$parsers.push(function(date) { + return { + type: 'date', + date: date.toUTCString() + }; + }); + } + }; + }); + })); beforeEach(inject(function(_$compile_, _$rootScope_) { $compile = _$compile_; $rootScope = _$rootScope_; @@ -1711,4 +1731,30 @@ describe('datepicker directive', function () { expect(getTitle()).toBe('2013'); }); }); + + describe('with an ngModelController having formatters and parsers', function() { + beforeEach(inject(function() { + // Custom date object. + $rootScope.date = { type: 'date', date: 'April 1, 2015 00:00:00' }; + + // Use dateModel directive to add formatters and parsers to the + // ngModelController that translate the custom date object. + element = $compile('')($rootScope); + $rootScope.$digest(); + })); + + it('updates the view', function() { + $rootScope.date = { type: 'date', date: 'April 15, 2015 00:00:00' }; + $rootScope.$digest(); + + expectSelectedElement(17); + }); + + it('updates the model', function() { + clickOption(17); + + expect($rootScope.date.type).toEqual('date'); + expect(new Date($rootScope.date.date)).toEqual(new Date('April 15, 2015 00:00:00')); + }); + }); });