AngularJS Redirect removing # - angularjs

I have in my a .cshtml file a view that has a button that "updates"
The update button works but I want to redirect to home directory.
In my .js file i first had
success(function (data) {
//Showing Success message
alert("Incident Added");
$location.path("\Home");
})
The link went from /Home/Create to /Home/Create#/Home and just stays there. I would like it to go back to my home directory. Essentially going back to the home view after Create.
I also tried this
success(function (data) {
//Showing Success message
alert("Incident Added");
$scope.$apply(function () {
$location.path("/Home");
});
})
And the url didn't add the #/Home afterwards but it stayed the same of /Home/Create and didnt' go to /Home. I would like to know what do I need to do to get it go back home. Or rather learn how to do redirects properly.

Assuming your $routProvider has this set for home
$routeProvider
.when('/', { templateUrl:'home.html',controller:'CtrlHome'})
you should be able to just use
$location.path("/");

$location service designed for single page application it works with $route service and easily be misunderstood
if you want a basic HTTP Redirect to MVC route (eg. your.app.com/Home) use $window.location
$window.location.href = "/Home";

Related

How to go to the url return by a restful service as response

I am calling a java restful service in angularjs
$http
.post($scope.url,datatest)
.success(function(data) {
console.log('success');
// console.log(data);
$scope.responseURL=data;
console.log($scope.responseURL);
})
.error(function(data) {
console.log('error');
});
Here the data is containing a url and I want to go to that url after success of service call.
Actually this is a transaction page where use will hit place Order button and then a service will be called which will return the url of payment getway.
Now I am supposed to redirect to that payment getway url.
Thanks
Edit:
Both the answer bellow are correct but the problem was, I was getting url as 'www.xyz.com/abc....' that's why it was being appended in the current url.
So I just prefixed the response url wiht 'http://' and it worked both way, the same tab and new tab as well.
You can use Angular $window:
$window.location.href = $scope.responseURL;
Inject $window object in your controller function.
You can use $location.path(url):
$location.path(data);
Edit: If you want to open it in another tab, you can try:
$window.open(data, '_blank');
Note: Don't forget to inject $location in your controller.

Angular Intercepting a particular http request and prompt for login

I am working on an angular app. It's an SPA. I am loading the profile(or myAccount) page into the home page when user clicks on a link.
<a href="#" ng-click="getProfileData()"/></a>
in my controller:
$scope.getProfileData(){
$http.get('/profile').then(
function success(){
},
function error(){
}
}
}
the link makes an ajax request through $http service of angular.
what I want to do is, when user clicks on the link, before making the ajax request to check if he's logged in or not. if not, open the sign in popup, and after sign in continue with the same request.
I've looked into $httpProvider.interceptors, but I'm still not sure how to do it, since I need to pause hold the $http request till the login is completed, modify the config by adding login details into it and then continue.
Is using of interceptors the correct option? If yes, how should I proceed towards my objective?
EDIT:
my primary concern is to continue with the same request. i.e. i don't want the user to click on profile link again after he has logged in. i can check if user is logged in or not before making the ajax request. if he is, then it's good. but if he's not, he has to log in (in the modal i pop up), and then he has to click on the profile link again. is there a way to continue the previous http request after login?
There are only three points in the application where the login modal should appear:
When you are on a welcome page and you click “Login”.
When you are not logged in and you attempt to visit a page that requires login.
When you attempt to make a request that requires a login(Ex:session expiration).
Determining which pages require a logged in user
Considering you are using ui router,you can secure routes of your application with the help of attaching additional properties to a route.Here we add a requireLogin property for each state.
app.config(function ($stateProvider) {
$stateProvider
.state('welcome', {
url: '/welcome',
// ...
data: {
requireLogin: false
}
})
.state('app', {
abstract: true,
// ...
data: {
requireLogin: true // this property will apply to all children of 'app'
}
})
});
For routes that do not require a login we set requireLogin to false.
Capturing attempted state changes
This is where we are going to capture the attempted state changes and inspect them for our requireLogin property.
app.run(function ($rootScope) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var requireLogin = toState.data.requireLogin;
if (requireLogin && typeof $rootScope.currentUser === 'undefined') {
event.preventDefault();
$rootScope.returnToState = toState.url;
// get me a login modal!
}
});
});
As you can see, if the route requires a login and $rootScope.currentUser is not yet set, we will prevent the attempted state change and show the modal.
Redirecting to initially requested url after login
The last part requires redirecting to the initially requested url after login.In our app.run we have set a variable $rootScope.returnToState = toState.url which we can use in our login controller to redirect.In our controller for the login page we can do something like this:
$scope.login = function(form) {
$scope.submitted = true;
if(form.$valid) {
Auth.login({
email: $scope.user.email,
password: $scope.user.password
})
.then( function() {
// Logged in, redirect to correct room
if( $rootScope.returnToState) {
$location.path($rootScope.returnToState);
} else {
//redirect all others after login to /rooms
$location.path('/home');
}
})
.catch( function(err) {
$scope.errors.other = err.message;
});
}
};
For further reference please refer to this blog post http://brewhouse.io/blog/2014/12/09/authentication-made-simple-in-single-page-angularjs-applications.html
This can help you build a rock solid authorization for your app which I think you might be looking for.
Why can't you just make another function call to verify, if the user is logged-in. And based on that fire up the ajax request that you are trying up there. Something like
$scope.getProfileData(){
if($scope.isLoggedin()){
$http.get('/profile').then(
function success(){
},
function error(){
}
}
}
};
$scope.isLoggedin = function(){
// Do some processing and return true/false based on if user is logged-in
};

redirecting a page with angular routing after successfully calling an api on express server

In a single page application using angular routing, how can I redirect a page after an api call. In my case, I want to redirect the user to the profile page after they have called the login api. So this is what I thought would work but it isn't.
On the client, main.js. I have the angular routing set up
app.config(function($routeProvider){ $routeProvider
//the home page display
.when('/', {
templateUrl: 'main.html',
controller: 'mainController'
})
.when('/login', {
templateUrl: 'login.html',
controller: 'loginController'
})
.when('/signUp', {
templateUrl: 'signUp.html',
controller: 'signUpController'
})
.when('/profile', {
templateUrl: 'profile.html',
//controller: 'mainController'
}); });
and from my controller I call the /login post api
app.controller('authController', function($scope, $http, $rootScope, $location){
$scope.user = {username: '', password: ''};
$scope.error_message = '';
$scope.login = function(){
$http.post('/login', $scope.user).success(function(data){
if(data.state == 'success'){
//set username authenticated property to true after successful log in
//I am only pasting some of my code here, more logic before controller
$rootScope.authenticated = true;
$rootScope.current_user = "james";
$location.path('/profile');
}
else{
$scope.error_message = data.message;
}
});
};
});
and here is my login api
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/success', // redirect to the secure profile section
failureRedirect : '/failure', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
and when it succeeds, it calls success which sends back the data which should trigger the callback in $http.post and redirect the page through $location.path('/profile');. However, the callback isn't called and my page displays the user information from res.send
//sends successful login state back to angular
router.get('/success', function(req, res){
res.send({state: 'success', user: req.user ? req.user : null});
});
Am I on the right track? I am just following microsoft's tutorial https://www.microsoftvirtualacademy.com/en-us/training-courses/mean-stack-jump-start-8442 but their completed page on github doesn't even work so it doesn't help me debug this problem of mine.
Using successRedirect and failureRedirect in passport will redirect the client to the specified pages, which will prevent your client-side angularJS routing from taking place. The reason you're seeing the user info after logging in is because your client is being redirected to the /success page, rather than actually responding to the original request. The client then fetches the success page with a GET request, and the new GET request is then responded to with the user info.
I would suggest leaving the node.js redirects out when using AngularJS, since you probably want to handle redirection on the client side:
router.post('/login', passport.authenticate('local-login'), function(req, res){
res.send(req.user);
});
The inline function will never execute if the user is not authenticated. Instead, passport will respond directly with a 401 error status, with a body of "Unauthorized". Therefore the success state is not required. On the client side, you should use the .error() function to deal with 401 errors, rather than checking your state variable:
$http.post('/login', $scope.user).success(function(user){
$rootScope.authenticated = true;
$rootScope.current_user = "james";
$location.path('/profile');
})
.error(function(err){
$scope.error_message = err;
});
If you want to pass back a more specific reason as to why the request was unauthorized (which is not always a good idea), you can use flash messages, and issue another GET request from angular to get a more detailed authorization failure message.
You seem to have a slight impedance mismatch on what the front-end and back-end want to do here. Your AngularJS code expects to make a POST to the API endpoint and get back a 200 (success) along with some JSON data which tells it about the success or failure of the login attempt.
The back-end, thinks it's going to receive a POST and then redirect the caller to a new location. At least that's the way I'm reading it. It's not simply sending back some data with an HTTP response code of 200 or an error code.
I think you want to tweak the back-end code to simply return data to the front-end to get the result you expect.
So far I haven't seen success in making Ajax calls to API redirecting to a page. We have a similar situation where API call may result in redirecting to a error page. We wanted to handle that in the server rather than asking UI (Angular) to do it. But it's just frustrating to see none of the methods of redirect like res.redirect are working.
Our scenario is Angular makes a API call through Ajax and API running on Node.js should redirect to a html page.

angular redirect to route + cache

I have a login form at my homepage. When an user submit form angular send post request to auth/login (laravel's default auth system -> it doesn't matter). It logs the user but then I want to refresh homepage view. I tried this:
$http({
data: {},
method: 'POST',
..
}).success(function(data) {
..
$templateCache.remove('/');
$location.path('/');
});
But it's not working. In console I see new request at homepage, but it doesn't change any data(when the user logs in he can see his nick instead of login form).
Where can be problem? (maybe problem can be that I'm changing location to the current? when I set $location.path('/something-else') it works).
I thought it's possible to remove 1 certain template from cache, but it's. You can only remove all templates with $templateCache.removeAll();

Restricting access to all routes but one

I'm starting to experiment with ExpressJS + AngularJS and I've run into a stressful situation.
My goal is to have one login page and one dashboard page, and using Passport + MongoDB I'll authenticate a user in and, if credentials are correct, redirect him to the dashboard page.
I've started with the angular-express-seed and modified it so I ended up with the previously mentioned views:
$routeProvider.
when('/login', {
templateUrl: 'partials/login',
controller: 'LoginCtrl'
}).
when('/dashboard', {
templateUrl: 'partials/dashboard',
controller: 'DashboardCtrl'
}).
otherwise({
redirectTo: '/login'
});
I'm serving each partial view with:
app.get('/partials/:name', routes.partials);
exports.partials = function (req, res) {
var name = req.params.name;
res.render('partials/' + name);
};
The login system is working correctly except for the part that I can access the dashboard directly (without loging in at all).
So I guess I need to figure out if the user if authenticated, before granting him access to the dashboard (or any other area for that matter).
I found this that does the trick:
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
and I would call it on every GET to a partial
app.get('/partials/:name', ensureAuthenticated, routes.partials);
The big problem here is that the login view is also a partial, and I don't want ensureAuthenticated to run when that's the view being requested.
Currently calling ensureAuthenticated on every partial request crashes any browser, no errors whatsoever.
What I've tried so far (and did not work):
function ensureAuthenticated(req, res, next) {
if ( req.route.params.name !== 'login' && req.isAuthenticated() ) { return next(); }
res.redirect('/login');
}
Also tried calling the login view with its own app.GET and not using ensureAuthenticated but somehow Angular flips off and does not even load.
Any ideas on how to resolve this ?
Thanks in advance.
It's unclear to me if the first (unmodified) version of ensureAuthenticated crashes your browsers, or the last version (in which you check for /partials/login), although no matter what, it shouldn't happen (if by 'crashing' you mean 'stalls', that's a tell-tale sign of Express not sending back a response)
But as an alternative, try this:
app.get('/partials/login', routes.partials);
app.get('/partials/:name', ensureAuthenticated, routes.partials);
Your routes.partials does have to check explicitly if it's called for the login route, because in that case the name parameter won't exist in req.params.
Just to make sure: do you have a server-side handler for /login as well? Otherwise the res.redirect('/login') isn't going to work.
I don't think that server side redirecting on XHR request is a good practice. XHR request should return 401 if the user is not authorized and the client side (Angular) should take the action as displaying notification message and redirecting user to the login partial. Look at this project for handling such requests. There are demo and blog post.

Resources