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

Commit 2635f0d

Browse files
committed
feat(modal): add pluggable resolve support
- Adds support for pluggable resolvers, namely for supporting UI Router's resolve handling Closes #3405 Closes #5078
1 parent fd59913 commit 2635f0d

File tree

3 files changed

+104
-20
lines changed

3 files changed

+104
-20
lines changed

Diff for: src/modal/docs/readme.md

+4
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,7 @@ Events fired:
129129
* `modal.closing` -
130130
This event is broadcast to the modal scope before the modal closes. If the listener calls preventDefault() on the event, then the modal will remain open.
131131
Also, the `$close` and `$dismiss` methods returns true if the event was executed. This event also includes a parameter for the result/reason and a boolean that indicates whether the modal is being closed (true) or dismissed.
132+
133+
##### UI Router resolves
134+
135+
If one wants to have the modal resolve using [UI Router's](https://github.com/angular-ui/ui-router) pre-1.0 resolve mechanism, one can call `$uibResolve.setResolver('$resolve')` in the configuration phase of the application. One can also provide a custom resolver as well, as long as the signature conforms to UI Router's [$resolve](http://angular-ui.github.io/ui-router/site/#/api/ui.router.util.$resolve).

Diff for: src/modal/modal.js

+51-20
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,52 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
5454
};
5555
})
5656

57+
/**
58+
* Pluggable resolve mechanism for the modal resolve resolution
59+
* Supports UI Router's $resolve service
60+
*/
61+
.provider('$uibResolve', function() {
62+
var resolve = this;
63+
this.resolver = null;
64+
65+
this.setResolver = function(resolver) {
66+
this.resolver = resolver;
67+
};
68+
69+
this.$get = ['$injector', '$q', function($injector, $q) {
70+
var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
71+
return {
72+
resolve: function(invocables, locals, parent, self) {
73+
if (resolver) {
74+
return resolver.resolve(invocables, locals, parent, self);
75+
}
76+
77+
var promises = [];
78+
79+
angular.forEach(invocables, function(value) {
80+
if (angular.isFunction(value) || angular.isArray(value)) {
81+
promises.push($q.resolve($injector.invoke(value)));
82+
} else if (angular.isString(value)) {
83+
promises.push($q.resolve($injector.get(value)));
84+
} else {
85+
promises.push($q.resolve(value));
86+
}
87+
});
88+
89+
return $q.all(promises).then(function(resolves) {
90+
var resolveObj = {};
91+
var resolveIter = 0;
92+
angular.forEach(invocables, function(value, key) {
93+
resolveObj[key] = resolves[resolveIter++];
94+
});
95+
96+
return resolveObj;
97+
});
98+
}
99+
};
100+
}];
101+
})
102+
57103
/**
58104
* A helper directive for the $modal service. It creates a backdrop element.
59105
*/
@@ -542,8 +588,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
542588
backdrop: true, //can also be false or 'static'
543589
keyboard: true
544590
},
545-
$get: ['$injector', '$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibModalStack',
546-
function ($injector, $rootScope, $q, $document, $templateRequest, $controller, $modalStack) {
591+
$get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
592+
function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
547593
var $modal = {};
548594

549595
function getTemplatePromise(options) {
@@ -552,20 +598,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
552598
options.templateUrl() : options.templateUrl);
553599
}
554600

555-
function getResolvePromises(resolves) {
556-
var promisesArr = [];
557-
angular.forEach(resolves, function(value) {
558-
if (angular.isFunction(value) || angular.isArray(value)) {
559-
promisesArr.push($q.when($injector.invoke(value)));
560-
} else if (angular.isString(value)) {
561-
promisesArr.push($q.when($injector.get(value)));
562-
} else {
563-
promisesArr.push($q.when(value));
564-
}
565-
});
566-
return promisesArr;
567-
}
568-
569601
var promiseChain = null;
570602
$modal.getPromiseChain = function() {
571603
return promiseChain;
@@ -602,7 +634,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
602634
}
603635

604636
var templateAndResolvePromise =
605-
$q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
637+
$q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
606638

607639
function resolveWithTemplate() {
608640
return templateAndResolvePromise;
@@ -629,14 +661,13 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
629661
});
630662

631663
var ctrlInstance, ctrlLocals = {};
632-
var resolveIter = 1;
633664

634665
//controllers
635666
if (modalOptions.controller) {
636667
ctrlLocals.$scope = modalScope;
637668
ctrlLocals.$uibModalInstance = modalInstance;
638-
angular.forEach(modalOptions.resolve, function(value, key) {
639-
ctrlLocals[key] = tplAndVars[resolveIter++];
669+
angular.forEach(tplAndVars[1], function(value, key) {
670+
ctrlLocals[key] = value;
640671
});
641672

642673
ctrlInstance = $controller(modalOptions.controller, ctrlLocals);

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

+49
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,51 @@
1+
describe('$uibResolve', function() {
2+
beforeEach(module('ui.bootstrap.modal'));
3+
4+
it('should resolve invocables and return promise with object of resolutions', function() {
5+
module(function($provide) {
6+
$provide.factory('bar', function() {
7+
return 'bar';
8+
});
9+
});
10+
11+
inject(function($q, $rootScope, $uibResolve) {
12+
$uibResolve.resolve({
13+
foo: 'bar',
14+
bar: $q.resolve('baz'),
15+
baz: function() {
16+
return 'boo';
17+
}
18+
}).then(function(resolves) {
19+
expect(resolves).toEqual({
20+
foo: 'bar',
21+
bar: 'baz',
22+
baz: 'boo'
23+
});
24+
});
25+
26+
$rootScope.$digest();
27+
});
28+
});
29+
30+
describe('with custom resolver', function() {
31+
beforeEach(module(function($provide, $uibResolveProvider) {
32+
$provide.factory('$resolve', function() {
33+
return {
34+
resolve: jasmine.createSpy()
35+
};
36+
});
37+
38+
$uibResolveProvider.setResolver('$resolve');
39+
}));
40+
41+
it('should call $resolve.resolve', inject(function($uibResolve, $resolve) {
42+
$uibResolve.resolve({foo: 'bar'}, {}, null, null);
43+
44+
expect($resolve.resolve).toHaveBeenCalledWith({foo: 'bar'}, {}, null, null);
45+
}));
46+
});
47+
});
48+
149
describe('$uibModal', function () {
250
var $animate, $controllerProvider, $rootScope, $document, $compile, $templateCache, $timeout, $q;
351
var $uibModal, $uibModalStack, $uibModalProvider;
@@ -1430,3 +1478,4 @@ describe('$uibModal', function () {
14301478
});
14311479
});
14321480
});
1481+

0 commit comments

Comments
 (0)