resolve resource in route - angularjs

Trying to send my resolved data to my controller. Things resolve fine, just can't figure out how to pass it into my controller. Right now I get get undefined when I try and log out the resolved data.
My module:
angular.module('projects').config(['$stateProvider',
function($stateProvider) {
$stateProvider
.state('view', {
url: '/:projectId',
templateUrl: 'view.html',
controller:'ProjectsClientController',
resolve:{
projectaa:function(apiResource, $stateParams){
apiResource.get({api_resource:'projects', api_value:$stateParams.projectId}).$promise.then(function(response){
return response;
});
}
}
})
}
])
angular.module('projects').controller('ProjectsClientController', ['$scope', '$stateParams', 'projectaa',
function($scope, $stateParams, projectaa) {
console.log(projectaa);
}
]);
What am I doing wrong?

It should also return the promise of apiResource.get so that the promise chain .then function would be accessible inside the controller
Code
projectaa: function(apiResource, $stateParams) {
return apiResource.get({
api_resource: 'projects',
api_value: $stateParams.projectId
}).$promise;
}
Inside controller you could get data by resolving that promise using .then
Controller
projectaa.then(function(data){
console.log(data); //you will get promise resolved here
//which will return data here
})

Related

My ui-router resolve don't return anything without errors

I have configure my MongoDb and API REST and when i tried to connect it with my Angular application i think it can't resolve.
I m learning MEAN application on this tutorial.
This is my ui-router configuration.
var app = angular.module('flapperNews', ['ui.router']);
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider,$urlRouterProvider){
$stateProvider
.state('home',{
url: '/home',
templateUrl: '/home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts',function(posts){
return posts.getAll();
}]
}
})
.state('posts',{
url: '/posts/{id}',
templateUrl: '/posts.html',
controller: 'PostCtrl'
});
$urlRouterProvider.otherwise('home');
}
]);
And this one is my factory.
app.factory('posts', ['$http',function (){
var o = {
getAll: function(){
return $http.get('/posts').success(function(data){
angular.copy(data,o.posts);
});
}
};
return o;
}]);
And this is the return of /posts
curl http://localhost:3000/posts/
[{"_id":"564f63d0e1f4efce4e36d863","name":"test","link":"http://test.com","__v":1,"comments":["564f70adf3340cab52f9d117"],"upvotes":2}]
The result is a white page whitout error.
Can you help me ?
Inject $http in your factory like below.
app.factory('posts', ['$http',function ($http){ your code }])
The issue that you have here is with the $http service in your factory. You need to inject it in the function, like this:
app.factory('posts', ['$http',function ($http){
var o = {
getAll: function(){
return $http.get('/posts').success(function(data){
angular.copy(data,o.posts);
});
}
};
return o;
}]);
It the rest of the code is fine, it should work without any issues. Here is one modified and simplified plunker that usses $q to return a promise instead of the $http since I don't have an http endpoint to call.
One error I see is that you haven't returned a promise in your resolve. getAll() uses an async api and thus you will have to return a promise. So change
posts.getAll();
to
posts.getAll().then(function(data) {
return data.data;
})
in your resolve. However, I am not sure if this will solve your problem completely.

Changing route with ui-router skipping resolve

I am using ui-router in my angular app.
I define the routing like this:
angular.module('app.product', [])
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('product', {
url: '/product/:product_id',
templateUrl: 'partial/product',
controller: 'productCtrl',
resolve: {
product: ['$http', '$stateParams',
function($http, $stateParams) {
return $http.get('/api/product/' + $stateParams.product_id);
}]
}
})
}])
At some point, I manually change the route on the client side using $state.go('product'). Here I already have the product data on the client side so there is no need for an extra $http request.
What is the best way to pass the data in the $state.go call and let ui-router know there is no need to make this request?
Should I build a service to handle this?
Use a service (something like the code below). Just note this is off the top of my head.
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('product', {
url: '/product/:product_id',
templateUrl: 'partial/product',
controller: 'productCtrl',
resolve: {
product: ['ProductCache', '$stateParams',
function(ProductCache, $stateParams) {
return ProductCache.getProduct($stateParams.product_id);
}]
}
});
}])
.factory('ProductCache', ['$http', '$q', function($http, $q) {
var cache = [];
return {
getProduct: function(id) {
// return the product if available, otherwise from the api
if(!cache[id]){
return $http.get('/api/product/' + id, function(result){
cache[id] = result.product; // or however your api return is structured
return cache[id];
});
}else{
// use .when() to ensure a promise is returned to the resolve function
return $q.when(cache[id]);
}
}
};
}]);

Angulajs wait till REST API returns data

I am using Trello API, which does not return promise. It has callback functions. I want to write a wrapper to it, which will wait till callback is executed and return the data.
I have written below code :
function getLoggedInMember() {
var deferred = $q.defer();
Trello.members.get("me", deferred.resolve);
deferred.promise.then(function (user) {
return user;
});
}
This function is in my Member Service. Below is my routeConfig :
angular.module('trelloDashboard').config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'Views/Login.html',
controller: 'LoginController'
})
.when('/Dashboard', {
templateUrl: 'Views/Dashboard.html',
controller: 'DashboardController',
resolve: {
user: function (MemberService) {
return MemberService.getLoggedInMember();
}
}
});}]);
This is obviously not working. Is there a way to achieve what I am trying to do here?
Thank you.
Try adding
deferred.promise.then(function (user) {
return user;
},function(error){
console.log("Error");
console.log(error);
//ur return statement
});
Not tested, but try:
.when('/Dashboard', {
templateUrl: 'Views/Dashboard.html',
controller: 'DashboardController',
resolve: {
user: MemberService.getLoggedInMember
}
But your getLoggedInMember function should return a promise.
According to angular docs:
resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired.
Here is what worked!
function getLoggedInMember() {
var deferred = $q.defer();
Trello.members.get("me", function(user){ deferred.resolve(user); });
return deferred.promise;
}
No change was needed in route config.
Thank you, #Benjamin :)

Angularjs: How to get my resolve data in my controller?

I am a bit confused. I am trying to get my resolve data in my controller. I read about these (and more) solutions, but can not get it working. It is all about the "spages".
http://jsfiddle.net/Avb4U/1/
http://www.jvandemo.com/how-to-resolve-angularjs-resources-with-ui-router/#
Angularjs resolve with controller as string
I hope this is not a duplicate question, because nothing did work for me from these solutions.
This is (part of all states) my state:
.state('root.search', {
url: '/search/:searchterm',
onEnter: ['$rootScope', function($rootScope) {
$rootScope.bodyclass = 'search';
}],
resolve : {
spages: ['$stateParams', 'SearchPages', function($stateParams, SearchPages) {
return SearchPages.get({'searchterm': $stateParams.searchterm});
}]
},
controller: 'searchCtrl',
views: {
'#': {
templateUrl: templateUrlFunction('search')
}
}
})
This is part of my controller:
app.controller('searchCtrl', ['$scope', 'spages', function($scope, spages) {
// spages should be already resolved and injected here
}
And this is my factory for the searchpages:
app.factory('SearchPages', ['$resource', function($resource) {
return $resource(null, {},
{
get: {
method: 'GET',
url: '/json/search/get/searchterm/:searchterm',
params: {searchterm: '#searchterm'}
}
});
}]);
Asfar as i do understand, spages should be resolved and injected in the controller now. But it is not.
The error i get is:
Error: [$injector:unpr] Unknown provider: spagesProvider <- spages
What do i do wrong? I am still learning...
Ok, what i did not realize is that i also have a controller in my template.
And i read: "You only need to specify controller once, in app.js. The second one, in the html code, is instantiated by the ngController directive, which does not know about `resolve', so it throws an exception."
Change your controller dependency from searchpages to SearchPages.
app.controller('searchCtrl', ['$scope', 'SearchPages', function($scope, searchpages) {
// searchpages should be already resolved and injected here
}

Using AngularJS Resolve in order to fetch API data before DOM is rendered

I am continuing to have issues where my templates and directives are throwing errors because they are trying to be $compiled before the data is actually set. This is because it takes time for the API response to get back.
Therefore, I am trying to convert my API call to work in the resolve property of my route, however I cannot figure out how to do it correctly. Here is what I have:
My State Provider w/ resolve property
$stateProvider
.state('dashboard', {
url: '/',
controller: 'LandingController',
resolve: {
data: ['API', function(API){
return API.Backups.getAll(function (data) {
return data.result;
});
}]
}
})
My controller
app.controller('LandingController', ['$scope', 'API', function ($scope, API, data) {
$scope.data = data;
......
I am using an Angular service that provides a $resource in order to get the API data, however something is not working still because my data parameter in the controller is still undefined.
I figured out what I needed. I just needed to return the $resource.$promise instead of just the $resource. After doing that, everything worked great!
Solution
$stateProvider
.state('dashboard', {
url: '/',
controller: 'LandingController',
resolve: {
res: ['API', function(API){
return API.Backups.getAll(function (data) {
return data.result;
}).$promise;
}]
}
})
Without the code for API.Backups.getAll() I can't tell, but the resolve function needs to return a "promise" which can be provided by the Angular $q:
resolve: ['$q', 'API', function($q, API) {
// 1. $q provides the deferred which satisfies the "promise" API
var deferred = $q.defer();
// 2. call your API
API.Backups.getAll(function (data) {
// 4. resolve the promise with data that was returned
deferred.resolve(data.result);
});
// 3. return the promise
return deferred.promise;
}]
The numbered comments show the order things will occur. Angular will not instantiate your controller until resolve() is called on the promise (deferred).
see: https://docs.angularjs.org/api/ng/service/$q

Resources