Skip to content

Instantly share code, notes, and snippets.

@MattWalker
Created July 29, 2013 18:17
Show Gist options
  • Save MattWalker/6106393 to your computer and use it in GitHub Desktop.
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.
// 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.')
@mustafasturan
Copy link

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;
}

@sveilleux
Copy link

F**king brutal! Thanks a lot you saved my ass.

@mustafasturan
Copy link

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;
}

@stodolos
Copy link

this is great! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment