feat(modal): add pluggable resolve support
- Adds support for pluggable resolvers, namely for supporting UI Router's resolve handling Closes #3405 Closes #5078
This commit is contained in:
@@ -129,3 +129,7 @@ Events fired:
|
||||
* `modal.closing` -
|
||||
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.
|
||||
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.
|
||||
|
||||
##### UI Router resolves
|
||||
|
||||
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).
|
||||
|
||||
+51
-20
@@ -54,6 +54,52 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
|
||||
};
|
||||
})
|
||||
|
||||
/**
|
||||
* Pluggable resolve mechanism for the modal resolve resolution
|
||||
* Supports UI Router's $resolve service
|
||||
*/
|
||||
.provider('$uibResolve', function() {
|
||||
var resolve = this;
|
||||
this.resolver = null;
|
||||
|
||||
this.setResolver = function(resolver) {
|
||||
this.resolver = resolver;
|
||||
};
|
||||
|
||||
this.$get = ['$injector', '$q', function($injector, $q) {
|
||||
var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;
|
||||
return {
|
||||
resolve: function(invocables, locals, parent, self) {
|
||||
if (resolver) {
|
||||
return resolver.resolve(invocables, locals, parent, self);
|
||||
}
|
||||
|
||||
var promises = [];
|
||||
|
||||
angular.forEach(invocables, function(value) {
|
||||
if (angular.isFunction(value) || angular.isArray(value)) {
|
||||
promises.push($q.resolve($injector.invoke(value)));
|
||||
} else if (angular.isString(value)) {
|
||||
promises.push($q.resolve($injector.get(value)));
|
||||
} else {
|
||||
promises.push($q.resolve(value));
|
||||
}
|
||||
});
|
||||
|
||||
return $q.all(promises).then(function(resolves) {
|
||||
var resolveObj = {};
|
||||
var resolveIter = 0;
|
||||
angular.forEach(invocables, function(value, key) {
|
||||
resolveObj[key] = resolves[resolveIter++];
|
||||
});
|
||||
|
||||
return resolveObj;
|
||||
});
|
||||
}
|
||||
};
|
||||
}];
|
||||
})
|
||||
|
||||
/**
|
||||
* A helper directive for the $modal service. It creates a backdrop element.
|
||||
*/
|
||||
@@ -542,8 +588,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
|
||||
backdrop: true, //can also be false or 'static'
|
||||
keyboard: true
|
||||
},
|
||||
$get: ['$injector', '$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibModalStack',
|
||||
function ($injector, $rootScope, $q, $document, $templateRequest, $controller, $modalStack) {
|
||||
$get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',
|
||||
function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {
|
||||
var $modal = {};
|
||||
|
||||
function getTemplatePromise(options) {
|
||||
@@ -552,20 +598,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
|
||||
options.templateUrl() : options.templateUrl);
|
||||
}
|
||||
|
||||
function getResolvePromises(resolves) {
|
||||
var promisesArr = [];
|
||||
angular.forEach(resolves, function(value) {
|
||||
if (angular.isFunction(value) || angular.isArray(value)) {
|
||||
promisesArr.push($q.when($injector.invoke(value)));
|
||||
} else if (angular.isString(value)) {
|
||||
promisesArr.push($q.when($injector.get(value)));
|
||||
} else {
|
||||
promisesArr.push($q.when(value));
|
||||
}
|
||||
});
|
||||
return promisesArr;
|
||||
}
|
||||
|
||||
var promiseChain = null;
|
||||
$modal.getPromiseChain = function() {
|
||||
return promiseChain;
|
||||
@@ -602,7 +634,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
|
||||
}
|
||||
|
||||
var templateAndResolvePromise =
|
||||
$q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
|
||||
$q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);
|
||||
|
||||
function resolveWithTemplate() {
|
||||
return templateAndResolvePromise;
|
||||
@@ -629,14 +661,13 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
|
||||
});
|
||||
|
||||
var ctrlInstance, ctrlLocals = {};
|
||||
var resolveIter = 1;
|
||||
|
||||
//controllers
|
||||
if (modalOptions.controller) {
|
||||
ctrlLocals.$scope = modalScope;
|
||||
ctrlLocals.$uibModalInstance = modalInstance;
|
||||
angular.forEach(modalOptions.resolve, function(value, key) {
|
||||
ctrlLocals[key] = tplAndVars[resolveIter++];
|
||||
angular.forEach(tplAndVars[1], function(value, key) {
|
||||
ctrlLocals[key] = value;
|
||||
});
|
||||
|
||||
ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
|
||||
|
||||
@@ -1,3 +1,51 @@
|
||||
describe('$uibResolve', function() {
|
||||
beforeEach(module('ui.bootstrap.modal'));
|
||||
|
||||
it('should resolve invocables and return promise with object of resolutions', function() {
|
||||
module(function($provide) {
|
||||
$provide.factory('bar', function() {
|
||||
return 'bar';
|
||||
});
|
||||
});
|
||||
|
||||
inject(function($q, $rootScope, $uibResolve) {
|
||||
$uibResolve.resolve({
|
||||
foo: 'bar',
|
||||
bar: $q.resolve('baz'),
|
||||
baz: function() {
|
||||
return 'boo';
|
||||
}
|
||||
}).then(function(resolves) {
|
||||
expect(resolves).toEqual({
|
||||
foo: 'bar',
|
||||
bar: 'baz',
|
||||
baz: 'boo'
|
||||
});
|
||||
});
|
||||
|
||||
$rootScope.$digest();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with custom resolver', function() {
|
||||
beforeEach(module(function($provide, $uibResolveProvider) {
|
||||
$provide.factory('$resolve', function() {
|
||||
return {
|
||||
resolve: jasmine.createSpy()
|
||||
};
|
||||
});
|
||||
|
||||
$uibResolveProvider.setResolver('$resolve');
|
||||
}));
|
||||
|
||||
it('should call $resolve.resolve', inject(function($uibResolve, $resolve) {
|
||||
$uibResolve.resolve({foo: 'bar'}, {}, null, null);
|
||||
|
||||
expect($resolve.resolve).toHaveBeenCalledWith({foo: 'bar'}, {}, null, null);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('$uibModal', function () {
|
||||
var $animate, $controllerProvider, $rootScope, $document, $compile, $templateCache, $timeout, $q;
|
||||
var $uibModal, $uibModalStack, $uibModalProvider;
|
||||
@@ -1430,3 +1478,4 @@ describe('$uibModal', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user