Created
July 29, 2013 18:17
-
-
Save MattWalker/6106393 to your computer and use it in GitHub Desktop.
A workaround to manage resolved dependencies between states using ui-router. Forgive any syntax blunderings, I've been in Coffeescript Land for a while.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ResolveService.js | |
angular.module('module').factory("ResolveService", function($q) { | |
var resolved; | |
// Dictionary for deferred | |
// object lookup | |
resolved = {}; | |
return { | |
// Create a resolved lookup | |
resolve: function(id, value) { | |
var deferred; | |
// Resolve if the deferred | |
// object exists | |
if (deferred = resolved[id]) { | |
if (deferred.promise != null) { | |
deferred.resolve(value); | |
} | |
} | |
// Store value to be wrapped and | |
// resolved with $q.when() | |
return resolved[id] = value; | |
}, | |
// Get a resolved value. | |
// Typically call this to retrieve a | |
// parent state's resolved object. | |
getResolved: function(id) { | |
// Return an existing resolved value | |
if (resolved[id]) { | |
return $q.when(resolved[id]); | |
} | |
// Or delegate to whenResolved if | |
// it hasn't been resolved yet. | |
return this.whenResolved(id); | |
}, | |
// Create a deferred object to be resolved. | |
// Use this to retrieve a resolved value | |
// within the same state. | |
whenResolved: function(id) { | |
resolved[id] = $q.defer(); | |
return resolved[id].promise; | |
} | |
}; | |
}); | |
// parent state | |
$stateProvider.state('parent', { | |
resolve: { | |
parentValue: function(ResolveService) { | |
var value = 'Hello from parent.'; | |
// Resolve and return 'value' | |
return ResolveService.resolve('parentValue',value); | |
} | |
}; | |
}); | |
// child state | |
$stateProvider.state('parent.child', { | |
controller: 'ChildController' | |
resolve: { | |
fooNeedsParent: function(ResolveService) { | |
// Use getResolved since parentValue is in an ancestor state. | |
return ResolveService.getResolved('parentValue').then( | |
function(parentValue){ | |
var foo = parentValue + " And foo."; | |
return ResolveService.resolve('foo', foo); | |
} | |
); | |
}, | |
barNeedsFoo: function(ResolveService) { | |
// Use whenResolved since foo is in the same state. | |
return ResolveService.whenResolved('foo').then( | |
function(foo){ | |
var bar = foo + " And bar."; | |
// Only necessary if you wanted to use this | |
// in another child's resolve. | |
return ResolveService.resolve('bar', bar); | |
} | |
); | |
} | |
}; | |
}); | |
// In ChildController... | |
expect(barNeedsFoo).toEqual('Hello from parent. And foo. And bar.') | |
F**king brutal! Thanks a lot you saved my ass.
Also update to whenResolved function to be able to resolve again if you need ( ex: signout and sign in )
whenResolved: function (id) {
if (!resolved[id]) {
resolved[id] = $q.defer();
}
else if (!resolved[id].promise) {
resolved[id] = $q.defer();
}
return resolved[id].promise;
}
this is great! Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If there is more than 1 property depends on same data to be resolved than there is a bug in the ResolveService whenResolved function.
we need to change
whenResolved: function(id) {
resolved[id] = $q.defer();
return resolved[id].promise;
}
code block to
whenResolved: function (id) {
if (!resolved[id]) {
resolved[id] = $q.defer();
}
return resolved[id].promise;
}