Angulajs wait till REST API returns data - angularjs

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 :)

Related

Run a function before running a controller

I have defined a factory auth as follows:
app.factory('auth', [function () {
var auth = {};
auth.getUser = function () {
... ...
// get user from cookie, cache, history, etc.
}
return auth
}]);
For many pages, I want to always run auth.getUser() before displaying them. To this end, at the moment, I use resolve, eg:
.state('home', {
url: '/home',
templateUrl: '/htmls/home.html',
controller: 'MainCtrl',
resolve: { getUser: ['auth', function (auth) { return auth.getUser() }]}
})
The pitfall of this implementation is I have to write lots of resolve. Thus, I am wondering if there is a way to implement this rule in controllers rather than state. Could anyone help?
Try checking the condition in
$rootScope.$on('$stateChangeStart', function (event, toState) {
//condition here and $state.go('')
});
I'm not sure if this works.
use angular run function
app.run(function() {
alert(1);
});
see http://jsfiddle.net/ysq3m/

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.

When is "onEnter" exactly executed

I'm looking for a best way to redirect my users from login/register form if they are already properly authenticated (and vice-versa)
So is it a good idea to do it onEnter? Will that function be executed before the associated controllers? Example:
...
.state('auth', {
templateUrl: "auth.html",
controller: 'PBAuthController as PBAuth',
onEnter: skipIfLoggedIn
})
...
function skipIfLoggedIn($q, $auth, $state) {
var deferred = $q.defer();
if ($auth.isAuthenticated()) {
$state.go('backend');
} else {
deferred.resolve();
}
return deferred.promise;
}
I just did a quick test and onEnter fires before the controller however there doesn't appear to be any way to prevent the controller from being instantiated.
In any case, here's how I've handled redirects in onEnter. The only thing to watch out for is to not interrupt the current state transition. You do this by waiting for the $state.transition promise to resolve...
onEnter: function($state, $auth) {
return $auth.isAuthenticated() && $state.transition.then(function() {
return $state.go('backend');
});
}

resolve resource in route

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

Angular ui-router templateProvider never called

I need to pass a route parameter to the server responding with a template, so I'm trying to use a templateProvider per several articles/other stack overflow docs.
I'm not getting any javascript errors, but the following templateProvider method is never even executed. When the templateUrl property is not commented out, this route works fine.
$stateProvider
.state('org.contacts.add', {
url: '/add',
views: {
'org#': {
// templateUrl: '/templates/issues/add',
controller: 'ContactsAddController',
templateProvider: function($route, $templateCache, $http) {
var url = '/templates/' + $route.current.params.org + '/contacts/add';
$http.get(url, {cache: $templateCache}).then(function(html){
return html;
});
}]
}
}
})
After some experimentation, it seems the $route was causing trouble. Taking that out and using $stateParams at least fires this code/controller.
However, while I see the ajax call firing and the proper html response, it's never loaded to the view.
templateProvider: function ($stateParams, $http, $templateCache) {
var url = '/templates/contacts/add';
$http.get(url, {cache: $templateCache}).then(function(html){
return html;
});
}
I'm guessing you need to return a $promise for this to work. Check out the example used on the UI-Router wiki:
$stateProvider.state('contacts', {
templateProvider: function ($timeout, $stateParams) {
return $timeout(function () {
return '<h1>' + $stateParams.contactId + '</h1>'
}, 100);
}
})
Notice the line that begins with return $timeout(.... Have you tried returning the $promise that is created by doing $http.get()?

Resources