Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 434c602

Browse files
committed
feat(datepicker): add disabled and ngDisabled support
- Adds support for `disabled` attribute - Adds support for `ng-disabled` Closes #4059 Closes #4814
1 parent 73efc78 commit 434c602

File tree

2 files changed

+132
-10
lines changed

2 files changed

+132
-10
lines changed

Diff for: src/datepicker/datepicker.js

+34-10
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
7575
this.activeDate = new Date();
7676
}
7777

78+
$scope.disabled = angular.isDefined($attrs.disabled) || false;
79+
if (angular.isDefined($attrs.ngDisabled)) {
80+
$scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {
81+
$scope.disabled = disabled;
82+
self.refreshView();
83+
});
84+
}
85+
7886
$scope.isActive = function(dateObject) {
7987
if (self.compare(dateObject.date, self.activeDate) === 0) {
8088
$scope.activeDateId = dateObject.uid;
@@ -127,7 +135,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
127135
};
128136

129137
this.isDisabled = function(date) {
130-
return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));
138+
return $scope.disabled || ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));
131139
};
132140

133141
this.customClass = function(date) {
@@ -185,7 +193,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
185193
$scope.keydown = function(evt) {
186194
var key = $scope.keys[evt.which];
187195

188-
if (!key || evt.shiftKey || evt.altKey) {
196+
if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
189197
return;
190198
}
191199

@@ -626,6 +634,7 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
626634
}
627635
}
628636
});
637+
629638
if (attrs.dateDisabled) {
630639
datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');
631640
}
@@ -743,17 +752,28 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
743752
element[0].focus();
744753
};
745754

755+
scope.disabled = angular.isDefined(attrs.disabled) || false;
756+
if (attrs.ngDisabled) {
757+
scope.$parent.$watch($parse(attrs.ngDisabled), function(disabled) {
758+
scope.disabled = disabled;
759+
});
760+
}
761+
746762
scope.$watch('isOpen', function(value) {
747763
if (value) {
748-
scope.position = appendToBody ? $position.offset(element) : $position.position(element);
749-
scope.position.top = scope.position.top + element.prop('offsetHeight');
764+
if (!scope.disabled) {
765+
scope.position = appendToBody ? $position.offset(element) : $position.position(element);
766+
scope.position.top = scope.position.top + element.prop('offsetHeight');
750767

751-
$timeout(function() {
752-
if (onOpenFocus) {
753-
scope.$broadcast('uib:datepicker.focus');
754-
}
755-
$document.bind('click', documentClickBind);
756-
}, 0, false);
768+
$timeout(function() {
769+
if (onOpenFocus) {
770+
scope.$broadcast('uib:datepicker.focus');
771+
}
772+
$document.bind('click', documentClickBind);
773+
}, 0, false);
774+
} else {
775+
scope.isOpen = false;
776+
}
757777
} else {
758778
$document.unbind('click', documentClickBind);
759779
}
@@ -808,6 +828,10 @@ function(scope, element, attrs, $compile, $parse, $document, $rootScope, $positi
808828
}
809829

810830
function documentClickBind(event) {
831+
if (!scope.isOpen && scope.disabled) {
832+
return;
833+
}
834+
811835
var popup = $popup[0];
812836
var dpContainsTarget = element[0].contains(event.target);
813837
// The popup node may not be an element node

Diff for: src/datepicker/test/datepicker.spec.js

+98
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,47 @@ describe('datepicker directive', function() {
12261226
});
12271227
});
12281228

1229+
describe('disabled', function() {
1230+
beforeEach(function() {
1231+
element = $compile('<uib-datepicker ng-model="date" disabled></uib-datepicker>')($rootScope);
1232+
$rootScope.$digest();
1233+
});
1234+
1235+
it('should have all dates disabled', function() {
1236+
element.find('.uib-day button').each(function(idx, elem) {
1237+
expect($(elem).prop('disabled')).toBe(true);
1238+
});
1239+
});
1240+
});
1241+
1242+
describe('ng-disabled', function() {
1243+
beforeEach(function() {
1244+
$rootScope.disabled = false;
1245+
element = $compile('<uib-datepicker ng-model="date" ng-disabled="disabled"></uib-datepicker>')($rootScope);
1246+
$rootScope.$digest();
1247+
});
1248+
1249+
it('should toggle disabled state with value of ng-disabled', function() {
1250+
element.find('.uib-day button').each(function(idx, elem) {
1251+
expect($(elem).prop('disabled')).toBe(false);
1252+
});
1253+
1254+
$rootScope.disabled = true;
1255+
$rootScope.$digest();
1256+
1257+
element.find('.uib-day button').each(function(idx, elem) {
1258+
expect($(elem).prop('disabled')).toBe(true);
1259+
});
1260+
1261+
$rootScope.disabled = false;
1262+
$rootScope.$digest();
1263+
1264+
element.find('.uib-day button').each(function(idx, elem) {
1265+
expect($(elem).prop('disabled')).toBe(false);
1266+
});
1267+
});
1268+
});
1269+
12291270
describe('setting datepickerPopupConfig', function() {
12301271
var originalConfig = {};
12311272
beforeEach(inject(function(uibDatepickerPopupConfig) {
@@ -2040,6 +2081,63 @@ describe('datepicker directive', function() {
20402081
});
20412082
});
20422083

2084+
describe('with disabled', function() {
2085+
var wrapElement;
2086+
2087+
beforeEach(function() {
2088+
$rootScope.isOpen = false;
2089+
wrapElement = $compile('<div><input ng-model="date" uib-datepicker-popup ng-required="true" ng-change="changeHandler()" is-open="isOpen" disabled><div>')($rootScope);
2090+
$rootScope.$digest();
2091+
});
2092+
2093+
it('should not open the popup', function() {
2094+
$rootScope.isOpen = true;
2095+
$rootScope.$digest();
2096+
2097+
expect($rootScope.isOpen).toBe(false);
2098+
expect(wrapElement.find('ul').length).toBe(0);
2099+
});
2100+
});
2101+
2102+
describe('with ng-disabled', function() {
2103+
var wrapElement;
2104+
2105+
beforeEach(function() {
2106+
$rootScope.disabled = false;
2107+
$rootScope.isOpen = false;
2108+
wrapElement = $compile('<div><input ng-model="date" uib-datepicker-popup ng-required="true" ng-change="changeHandler()" is-open="isOpen" ng-disabled="disabled"><div>')($rootScope);
2109+
$rootScope.$digest();
2110+
});
2111+
2112+
it('should not open the popup when disabled', function() {
2113+
$rootScope.isOpen = true;
2114+
$rootScope.$digest();
2115+
2116+
expect($rootScope.isOpen).toBe(true);
2117+
expect(wrapElement.find('ul').length).toBe(1);
2118+
2119+
$rootScope.isOpen = false;
2120+
$rootScope.$digest();
2121+
2122+
expect($rootScope.isOpen).toBe(false);
2123+
expect(wrapElement.find('ul').length).toBe(0);
2124+
2125+
$rootScope.disabled = true;
2126+
$rootScope.isOpen = true;
2127+
$rootScope.$digest();
2128+
2129+
expect($rootScope.isOpen).toBe(false);
2130+
expect(wrapElement.find('ul').length).toBe(0);
2131+
2132+
$rootScope.disabled = false;
2133+
$rootScope.isOpen = true;
2134+
$rootScope.$digest();
2135+
2136+
expect($rootScope.isOpen).toBe(true);
2137+
expect(wrapElement.find('ul').length).toBe(1);
2138+
});
2139+
});
2140+
20432141
describe('with datepicker-popup-template-url', function() {
20442142
beforeEach(function() {
20452143
$rootScope.date = new Date();

0 commit comments

Comments
 (0)