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

Commit 0d79005

Browse files
Daniel Smithwesleycho
Daniel Smith
authored andcommitted
fix(angular): add compatibility with Angular 1.6
- Change how ngModelOptions is used to conform to Angular 1.6 - Catch rejections as per change to $q Closes #6427 Fixes #6360
1 parent e538d2f commit 0d79005

File tree

10 files changed

+119
-48
lines changed

10 files changed

+119
-48
lines changed

Diff for: Gruntfile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = function(grunt) {
99
grunt.util.linefeed = '\n';
1010

1111
grunt.initConfig({
12-
ngversion: '1.5.8',
12+
ngversion: '1.6.1',
1313
bsversion: '3.3.7',
1414
modules: [],//to be filled in by build task
1515
pkg: grunt.file.readJSON('package.json'),

Diff for: package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
"url": "https://github.com/angular-ui/bootstrap.git"
3131
},
3232
"devDependencies": {
33-
"angular": "1.5.8",
34-
"angular-mocks": "1.5.8",
35-
"angular-sanitize": "1.5.8",
33+
"angular": "1.6.1",
34+
"angular-mocks": "1.6.1",
35+
"angular-sanitize": "1.6.1",
3636
"grunt": "^0.4.5",
3737
"grunt-cli": "^1.2.0",
3838
"grunt-contrib-concat": "^1.0.0",

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ describe('uib-accordion', function() {
551551
});
552552

553553
it('attaches the same scope to the transcluded heading and body', function() {
554-
expect(findGroupLink(0).find('span.ng-scope').scope().$id).toBe(findGroupBody(0).find('span').scope().$id);
554+
expect(findGroupLink(0).scope().$id).toBe(findGroupBody(0).scope().$id);
555555
});
556556

557557
it('should wrap the transcluded content in a span', function() {
@@ -580,7 +580,7 @@ describe('uib-accordion', function() {
580580
});
581581

582582
it('attaches the same scope to the transcluded heading and body', function() {
583-
expect(findGroupLink(0).find('span.ng-scope').scope().$id).toBe(findGroupBody(0).find('span').scope().$id);
583+
expect(findGroupLink(0).scope().$id).toBe(findGroupBody(0).scope().$id);
584584
});
585585

586586
it('should have disabled styling when is-disabled is true', isDisabledStyleCheck);

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('uib-alert', function() {
3636
}
3737

3838
function findContent(index) {
39-
return element.find('div[ng-transclude] span').eq(index);
39+
return element.find('div[ng-transclude]').eq(index);
4040
}
4141

4242
it('should expose the controller to the view', function() {

Diff for: src/collapse/collapse.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ angular.module('ui.bootstrap.collapse', [])
7272
to: getScrollFromElement(element[0])
7373
}).then(expandDone);
7474
}
75-
});
75+
}, angular.noop);
7676
}
7777

7878
function expandDone() {
@@ -111,7 +111,7 @@ angular.module('ui.bootstrap.collapse', [])
111111
to: cssTo
112112
}).then(collapseDone);
113113
}
114-
});
114+
}, angular.noop);
115115
}
116116

117117
function collapseDone() {

Diff for: src/datepicker/datepicker.js

+45-15
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
104104
$scope.$watch('datepickerOptions.' + key, function(value) {
105105
if (value) {
106106
if (angular.isDate(value)) {
107-
self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
107+
self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.getOption('timezone'));
108108
} else {
109109
if ($datepickerLiteralWarning) {
110110
$log.warn('Literal date support has been deprecated, please switch to date object usage');
@@ -114,7 +114,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
114114
}
115115
} else {
116116
self[key] = datepickerConfig[key] ?
117-
dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) :
117+
dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.getOption('timezone')) :
118118
null;
119119
}
120120

@@ -161,14 +161,13 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
161161

162162
this.init = function(ngModelCtrl_) {
163163
ngModelCtrl = ngModelCtrl_;
164-
ngModelOptions = ngModelCtrl_.$options ||
165-
$scope.datepickerOptions.ngModelOptions ||
166-
datepickerConfig.ngModelOptions;
164+
ngModelOptions = extractOptions(ngModelCtrl);
165+
167166
if ($scope.datepickerOptions.initDate) {
168-
self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date();
167+
self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.getOption('timezone')) || new Date();
169168
$scope.$watch('datepickerOptions.initDate', function(initDate) {
170169
if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
171-
self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
170+
self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.getOption('timezone'));
172171
self.refreshView();
173172
}
174173
});
@@ -178,8 +177,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
178177

179178
var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
180179
this.activeDate = !isNaN(date) ?
181-
dateParser.fromTimezone(date, ngModelOptions.timezone) :
182-
dateParser.fromTimezone(new Date(), ngModelOptions.timezone);
180+
dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')) :
181+
dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
183182

184183
ngModelCtrl.$render = function() {
185184
self.render();
@@ -192,7 +191,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
192191
isValid = !isNaN(date);
193192

194193
if (isValid) {
195-
this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone);
194+
this.activeDate = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
196195
} else if (!$datepickerSuppressError) {
197196
$log.error('Datepicker directive: "ng-model" value must be a Date object');
198197
}
@@ -209,17 +208,17 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
209208
}
210209

211210
var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
212-
date = dateParser.fromTimezone(date, ngModelOptions.timezone);
211+
date = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));
213212
ngModelCtrl.$setValidity('dateDisabled', !date ||
214213
this.element && !this.isDisabled(date));
215214
}
216215
};
217216

218217
this.createDateObject = function(date, format) {
219218
var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
220-
model = dateParser.fromTimezone(model, ngModelOptions.timezone);
219+
model = dateParser.fromTimezone(model, ngModelOptions.getOption('timezone'));
221220
var today = new Date();
222-
today = dateParser.fromTimezone(today, ngModelOptions.timezone);
221+
today = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
223222
var time = this.compare(date, today);
224223
var dt = {
225224
date: date,
@@ -265,9 +264,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
265264

266265
$scope.select = function(date) {
267266
if ($scope.datepickerMode === self.minMode) {
268-
var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0);
267+
var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0);
269268
dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
270-
dt = dateParser.toTimezone(dt, ngModelOptions.timezone);
269+
dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone'));
271270
ngModelCtrl.$setViewValue(dt);
272271
ngModelCtrl.$render();
273272
} else {
@@ -352,6 +351,37 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
352351
$scope.datepickerMode = mode;
353352
$scope.datepickerOptions.datepickerMode = mode;
354353
}
354+
355+
function extractOptions(ngModelCtrl) {
356+
var ngModelOptions;
357+
358+
if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
359+
// guarantee a value
360+
ngModelOptions = ngModelCtrl.$options ||
361+
$scope.datepickerOptions.ngModelOptions ||
362+
datepickerConfig.ngModelOptions ||
363+
{};
364+
365+
// mimic 1.6+ api
366+
ngModelOptions.getOption = function (key) {
367+
return ngModelOptions[key];
368+
};
369+
} else { // in angular >=1.6 $options is always present
370+
// ng-model-options defaults timezone to null; don't let its precedence squash a non-null value
371+
var timezone = ngModelCtrl.$options.getOption('timezone') ||
372+
($scope.datepickerOptions.ngModelOptions ? $scope.datepickerOptions.ngModelOptions.timezone : null) ||
373+
(datepickerConfig.ngModelOptions ? datepickerConfig.ngModelOptions.timezone : null);
374+
375+
// values passed to createChild override existing values
376+
ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance
377+
.createChild(datepickerConfig.ngModelOptions) // lowest precedence
378+
.createChild($scope.datepickerOptions.ngModelOptions)
379+
.createChild(ngModelCtrl.$options) // highest precedence
380+
.createChild({timezone: timezone}); // to keep from squashing a non-null value
381+
}
382+
383+
return ngModelOptions;
384+
}
355385
}])
356386

357387
.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {

Diff for: src/datepickerPopup/popup.js

+29-11
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
3232

3333
this.init = function(_ngModel_) {
3434
ngModel = _ngModel_;
35-
ngModelOptions = angular.isObject(_ngModel_.$options) ?
36-
_ngModel_.$options :
37-
{
38-
timezone: null
39-
};
35+
ngModelOptions = extractOptions(ngModel);
4036
closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?
4137
$scope.$parent.$eval($attrs.closeOnDateSelection) :
4238
datepickerPopupConfig.closeOnDateSelection;
@@ -127,13 +123,13 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
127123
value = new Date(value);
128124
}
129125

130-
$scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);
126+
$scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
131127

132128
return dateParser.filter($scope.date, dateFormat);
133129
});
134130
} else {
135131
ngModel.$formatters.push(function(value) {
136-
$scope.date = dateParser.fromTimezone(value, ngModelOptions.timezone);
132+
$scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));
137133
return value;
138134
});
139135
}
@@ -185,7 +181,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
185181

186182
$scope.isDisabled = function(date) {
187183
if (date === 'today') {
188-
date = dateParser.fromTimezone(new Date(), ngModelOptions.timezone);
184+
date = dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));
189185
}
190186

191187
var dates = {};
@@ -242,7 +238,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
242238
date = new Date($scope.date);
243239
date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
244240
} else {
245-
date = dateParser.fromTimezone(today, ngModelOptions.timezone);
241+
date = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));
246242
date.setHours(0, 0, 0, 0);
247243
}
248244
}
@@ -333,11 +329,11 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
333329
if (angular.isString(viewValue)) {
334330
var date = parseDateString(viewValue);
335331
if (!isNaN(date)) {
336-
return dateParser.toTimezone(date, ngModelOptions.timezone);
332+
return dateParser.toTimezone(date, ngModelOptions.getOption('timezone'));
337333
}
338334
}
339335

340-
return ngModel.$options && ngModel.$options.allowInvalid ? viewValue : undefined;
336+
return ngModelOptions.getOption('allowInvalid') ? viewValue : undefined;
341337
}
342338

343339
function validator(modelValue, viewValue) {
@@ -412,6 +408,28 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
412408
}
413409
}
414410

411+
function extractOptions(ngModelCtrl) {
412+
var ngModelOptions;
413+
414+
if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing
415+
// guarantee a value
416+
ngModelOptions = angular.isObject(ngModelCtrl.$options) ?
417+
ngModelCtrl.$options :
418+
{
419+
timezone: null
420+
};
421+
422+
// mimic 1.6+ api
423+
ngModelOptions.getOption = function (key) {
424+
return ngModelOptions[key];
425+
};
426+
} else { // in angular >=1.6 $options is always present
427+
ngModelOptions = ngModelCtrl.$options;
428+
}
429+
430+
return ngModelOptions;
431+
}
432+
415433
$scope.$on('uib:datepicker.mode', function() {
416434
$timeout(positionPopup, 0, false);
417435
});

Diff for: src/modal/modal.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.sta
419419
var appendToElement = modal.appendTo,
420420
currBackdropIndex = backdropIndex();
421421

422-
if (!appendToElement.length) {
423-
throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
424-
}
425-
426422
if (currBackdropIndex >= 0 && !backdropDomEl) {
427423
backdropScope = $rootScope.$new(true);
428424
backdropScope.modalOptions = modal;
@@ -699,6 +695,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.sta
699695
modalOptions.resolve = modalOptions.resolve || {};
700696
modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);
701697

698+
if (!modalOptions.appendTo.length) {
699+
throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');
700+
}
701+
702702
//verify options
703703
if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) {
704704
throw new Error('One of component or template or templateUrl options is required.');

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ describe('$uibModal', function() {
296296

297297
function open(modalOptions, noFlush, noDigest) {
298298
var modal = $uibModal.open(modalOptions);
299+
modal.opened['catch'](angular.noop);
300+
modal.result['catch'](angular.noop);
299301

300302
if (!noDigest) {
301303
$rootScope.$digest();
@@ -1612,7 +1614,7 @@ describe('$uibModal', function() {
16121614
var windowEl = $compile('<div uib-modal-window template-url="window.html">content</div>')($rootScope);
16131615
$rootScope.$digest();
16141616

1615-
expect(windowEl.html()).toBe('<div ng-transclude=""><span class="ng-scope">content</span></div>');
1617+
expect(windowEl.html()).toBe('<div ng-transclude="">content</div>');
16161618
}));
16171619
});
16181620

@@ -1736,16 +1738,19 @@ describe('$uibModal', function() {
17361738
ds[x] = {index: i, deferred: $q.defer(), reject: reject};
17371739

17381740
var scope = $rootScope.$new();
1741+
var failed = false;
17391742
scope.index = i;
17401743
open({
17411744
template: '<div>' + i + '</div>',
17421745
scope: scope,
17431746
resolve: {
1744-
x: function() { return ds[x].deferred.promise; }
1747+
x: function() { return ds[x].deferred.promise['catch'](function () {
1748+
failed = true;
1749+
}); }
17451750
}
17461751
}, true).opened.then(function() {
17471752
expect($uibModalStack.getTop().value.modalScope.index).toEqual(i);
1748-
actual += i;
1753+
if (!failed) { actual += i; }
17491754
});
17501755
});
17511756

0 commit comments

Comments
 (0)