Reputation: 3573
I'm just getting started with Angular and Express and facing tough times with it. I come from a java background and want to learn Angular and Express and therefore trying out to build one small application.
What I'm trying to do: I have given a password reset link to user so as to change his password. The link is something like:
localhost:9000/reset/:token
Now, I have created a simple view which shows an input box to change his password if token is valid otherwise prints an error if token is invalid based on ng-show property of angular.
Problem: Before I can render my above created view, I want ui-router to check if the :token is valid or not. I will be using the information of validity of token in my controller to control ng-show property mentioned above.
After reading this I tried to leverage the $stateProvider.state functionality with a resolve so as to get the response of validation of token as pre-requisite. This will help me when rendering the actual view where I'm using ng-show technique to show error message or input box to change the password based on the ui-router resolve promiseObject.
What is the issue now ?
Well, after breaking my head for too long, I decided to post my question over here. Can anyone please help me here ?
My questions:
1. I'm able to get the data/err from the api call but somehow ui-router is not injecting it in my controller. Can anyone tell me am I doing anything wrong here ?
2. Right now if the token is not valid, I'm returning a 404 in response from my backend api. But the factory method in frontend takes it as err (Is this expected in Node.js ?) and the err is thrown which results in deferred.reject(). Now, if I go with ui-router definition, if the promise is not resolved then the view won't be rendered, right ? Is there any way by which I can pass this err also to my controller ? Reason why I'm asking to pass err is, my view's ng-show logic is based on the response code (4xx/2xx) depending on which I'll show error message or input box.
Code snippets:
Factory Method which calls the rest api:
isPasswordResetTokenValid: function(token, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();
return User.getUserByPasswordResetToken(token,
function(data) {
deferred.resolve(data);
return cb(data);
},
function(err) {
deferred.reject(err);
return cb(err);
}.bind(this)).$promise;
}
'use strict';
angular.module('scrubApp')
.config(function ($stateProvider) {
$stateProvider
.state('passwordreset', {
url: '/reset/:token',
templateUrl: 'app/account/passwordreset/passwordreset.html',
resolve: {
promiseObj2: function($stateParams, Auth){
var token = $stateParams.token;
console.log(token);
var response = Auth.isPasswordResetTokenValid({token: token})
.then( function(response) {
console.log(response); // shows response
if(response.status == 404) {
//$scope.token-expiry = true;
return response;
}
if(response.status == 200) {
// $scope.user = response.data;
}
})
.catch( function(err) {
console.log(err); // shows error
return err;
});
}
},
controller: 'ResetPasswordCtrl'
});
});
ResetPasswordCtrl controller:
'use strict';
angular.module('myApp')
.controller('ResetPasswordCtrl', function ($scope, User, Auth, Mailer, $stateParams, promiseObj2) {
$scope.errors = {};
$scope.user = {};
console.log(promiseObj2); // This is coming undefined
$scope.isTokenExpired = promiseObj2; // Not able to inject promiseObj2
$scope.isFormSubmitted = false;
});
Thanks in advance
Upvotes: 2
Views: 868
Reputation: 136184
Your resolve promiseObj2
should return a promise from promise service, so that your controller will wait till promise gets resolved.
return Auth.isPasswordResetTokenValid({token: token})
Update
If you want to handle some logic on failure of your token request then you could handle it in your promise itself, that can do couple of thing like
$state.go('login')
or $state.go('error')
page. Code
promiseObj2: function($stateParams, Auth, $state){
var token = $stateParams.token;
console.log(token);
return Auth.isPasswordResetTokenValid({token: token}) //added return here
.then( function(response) {
console.log(response); // shows response
if(response.status == 404) {
$state.go('error')
}
if(response.status == 200) {
return response;
}
})
.catch( function(err) {
console.log(err); // shows error
return err;
});
}
.then
of promiseObj2
object that will have information about error message. So that error information is return
to the controllerCode
promiseObj2: function($stateParams, Auth, $state){
var token = $stateParams.token;
console.log(token);
return Auth.isPasswordResetTokenValid({token: token}) //added return here
.then( function(response) {
console.log(response); // shows response
if(response.status == 404) {
return {status: 404, data: "doen't found resource"}
}
if(response.status == 200) {
return response;
}
})
.catch( function(err) {
console.log(err); // shows error
return err;
});
}
Then inside controller we will get resolve the promise of promiseObj2
object and then you will get the value of error in the .then
function of it.
angular.module('myApp')
.controller('ResetPasswordCtrl', function ($scope, User, Auth, Mailer, $stateParams, promiseObj2) {
$scope.errors = {};
$scope.user = {};
promiseObj2.then(function(resp){
console.log(resp)
$scope.isTokenExpired = resp.isTokenExpired;
}, function(err){
console.log(err)
})
});
Update
If we want to handle a condition where server return 4XX
status that means our ajax will call catch function that won't return promise though. We could solve this case by creating custom promise using $q
and we will resolve it from the promiseObj2
Code
promiseObj2: function($stateParams, Auth, $state, $q){
var token = $stateParams.token,
deffered = $q.defer();
console.log(token);
Auth.isPasswordResetTokenValid({token: token}) //added return here
.then( function(response) {
console.log(response); // shows response
if(response.status == 404) {
//return {status: 404, data: "doen't found resource"}
deffered.resolve({status: 404, data: "doen't found resource"});
}
if(response.status == 200) {
//return response;
deffered.resolve(response);
}
})
.catch( function(err) {
console.log(err); // shows error
deffered.resolve(err);
});
return deffered.promise;
}
Upvotes: 2