Angularjs $location.path('...') doesn't work - angularjs

I'm working on authentication with angularjs, so after connecting my user I want to redirect him to the home page:
$scope.submit = function(user) {
var request = {
method: 'POST',
url: 'http://localhost:9001/signIn',
headers: {
'Content-Type': 'application/json'
},
data: {
"email": user.email,
"password": user.password,
"rememberMe": true
}
};
$http(request).then(function(data) {
$location.path('/home');
}, function(error) {
console.log(error);
});
};
here is my configuration:
app.config(function($urlRouterProvider, $stateProvider, $httpProvider, $authProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home',
controller: 'HomeCtrl',
resolve: {
authenticated: function($q, $location, $auth) {
var deferred = $q.defer();
if (!$auth.isAuthenticated()) {
$location.path('/signIn');
} else {
deferred.resolve();
}
return deferred.promise;
}
}
})
.state('signIn', {
url: '/signIn',
templateUrl: '/signIn',
controller: 'SignInCtrl'
});
});
I tried this:
$http(request).then(function(data) {
$scope.$evalAsync(function() {
$location.path('/home');
});
console.log(data);
}, function(error) {
console.log(error);
});
also :
$location.path('/home');
$location.replace();
Neither of the above work, any help is greatly appreciated.

The home state resolver function fails to resolve or reject the $q.defer promise when $auth.isAuthenticated() returns false. This will cause the promise to hang and create a memory leak.
//ERRONEOUS CODE
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home',
controller: 'HomeCtrl',
resolve: {
authenticated: function($q, $location, $auth) {
var deferred = $q.defer();
if (!$auth.isAuthenticated()) {
$location.path('/signIn');
//FAILS to resolve or reject promise
} else {
deferred.resolve();
}
return deferred.promise;
}
}
})
Instead return a rejection when not authenticated:
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home',
controller: 'HomeCtrl',
resolve: {
authenticated: function($q, $location, $auth) {
//var deferred = $q.defer();
if ($auth.isAuthenticated()) {
return $q.resolve("AUTHENTICATED");
};
//otherwise
return $q.reject("NOT AUTHENTICATED");
})
}
})
When a resolver function returns a rejected promise, the state change will be prevented and the $stateChangeError event will be broadcast on $rootScope.

Related

error while calling to $modal service from run block

In my main module i have used ui-bootstrap modal for checking login authentication.From run block i have called to loginModal service but it is giving Error
TypeError: loginModal is not a function
angular.module('myApp', ['ui.router', 'ui.bootstrap', 'loginServices','leaveServices']). config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider.
state('home', {
url:'/home',
data: {
requireLogin: false
},
views: {
'': {
templateUrl: 'partials/templates/assets/home.html'
}
}
}).
state('home.about', {
url: '/about',
templateUrl: 'partials/templates/assets/about.html'
}).
state('home.contact', {
url: '/contact',
templateUrl: 'partials/templates/assets/contactUs.html'
}).
state('/login', {
url: '/login',
data: {
requireLogin: false
},
templateUrl: 'partials/login.html',
controller: loginUserController
}).
state('/register', {
url:'/register',
data: {
requireLogin: false
},
templateUrl: 'partials/registerUser.html',
controller: registerController
}).
state('/getAllUsers', {
url: '/getAllUsers',
data: {
requireLogin: false
},
templateUrl: 'partials/getAllUsers.html',
controller: getUsersController
}).
state('/updateUser', {
url : '/updateUser/:id/:name',
data: {
requireLogin: true
},
params: {'id':null, 'name':null},
templateUrl: 'partials/updateUser.html',
controller: updateUserController
}).
state('/userLeave', {
url : '/userLeave:name',
data: {
requireLogin: true
},
params: {'name': null},
templateUrl: 'partials/userLeave.html',
controller: userLeaveController
}).
state('/leaveRequest', {
url : '/leaveRequest',
data: {
requireLogin: true
},
templateUrl: 'partials/leaveRequest.html'
});
}])
.run(function ($rootScope, $state, loginModal) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var requireLogin = toState.data.requireLogin;
console.log('going to state '+toState.name);
if (requireLogin && typeof $rootScope.currentUser === 'undefined') {
event.preventDefault();
loginModal().then(function () {
return $state.go(toState.name, toParams);
})
.catch(function () {
return $state.go('/login');
});
}
});
})
.factory('loginModal', function ($modal, $rootScope) {
function assignCurrentUser (user) {
$rootScope.currentUser = user;
return user;
}
return function() {
var instance = $modal.open({
templateUrl: 'partials/login.html',
controller: loginUserController
});
return instance.result.then(assignCurrentUser);
}
});
here login controller
loginUserController.$inject = ['$scope','$http', 'loginFactory', '$location', '$state'];
function loginUserController($scope,$http,loginFactory,$location, $state){
$scope.validateLogin = function(name,password){
$http.get("http://localhost:3010/validateLogin?userName="+name+"&password="+password)
.then(function(response) {
if(response.data.length != 0) {
console.log("logged user data is "+JSON.stringify(response.data));
$state.transitionTo('/userLeave', {name: name});
// $scope.$close(response);
}
else
$scope.inValidUser = 'Invalid User';
});
};
$scope.cancel = $scope.$dismiss;
}
Could be because you're using an Angular service which expects a constructor which in turn, should not be returning something.
Try changing to a factory, eg
.factory('loginModal', ...

$state.go() is not refreshing my ionic page

I have tried several method but $state.go() is not refreshing my page.Here is my controller. All process works but i cannot reload the browse page using $state.go() function.
angular.module('kawaadi.controllers', [])
.controller('AppCtrl', function ($scope, Service, $ionicLoading, $ionicModal, $ionicPopup, $timeout, $state, $http,$location) {
$scope.loginData = {};
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope
}).then(function (modal) {
$scope.modal = modal;
});
$scope.closeLogin = function () {
$scope.modal.hide();
};
$scope.login = function () {
$scope.modal.show();
};
$scope.logout = function () {
localStorage.setItem("token", "");
$state.go('login');
};
$scope.statusData = function (pid, uid, status) {
$ionicLoading.show({
template: 'Processing...'
});
Service.change_status(pid, uid, status, $http).success(function (data) {
if (data.status === 'success' && data.notification_status === 'success') {
$ionicLoading.hide();
var alertPopup = $ionicPopup.alert({
title: 'Success!',
template: 'Successfully changed and notification has been send!'
});
} else if (data.status === 'success' && data.notification_status === 'failure') {
$ionicLoading.hide();
var alertPopup = $ionicPopup.alert({
title: 'Success!',
template: 'Successfully changed but failed to send notification!!'
});
}
alertPopup.then(function (res) {
if (res == true) {
$state.go('app.browse');
}
});
}).error(function (data) {
var alertPopup = $ionicPopup.alert({
title: 'Process failed!',
template: 'Some thing went wrong!'
});
});
}
})
and here is my url router
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'templates/auth.html',
controller: 'LoginCtrl'
})
.state('app', {
url: '/app',
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.search', {
url: '/search',
views: {
'menuContent': {
templateUrl: 'templates/search.html'
}
}
})
.state('app.browse', {
url: '/browse',
views: {
'menuContent': {
templateUrl: 'templates/browse.html',
controller: 'pickupCtrl'
}
}
})
.state('app.playlists', {
url: '/playlists',
views: {
'menuContent': {
templateUrl: 'templates/playlists.html',
controller: 'PlaylistsCtrl'
}
}
})
.state('app.single', {
url: '/playlists/:playlistId',
views: {
'menuContent': {
templateUrl: 'templates/playlist.html',
controller: 'PlaylistCtrl'
}
}
});
});
Please guide me. Thanks in advance
Please modify all your states as
.state('emailConfirmation',{
cache: false,
url:"/emailConfirmation",
templateUrl:"app/session/emailConfirmation.html",
controller: 'EmailConfirmationCtrl'
})
and to reload the current page please use these command
$state.transitionTo($state.current, $stateParams, {
reload: true,
inherit: false,
notify: true
});
If you want to force reload the current state, then you probably need to use $state.go($state.current.name, $state.params, {reload: true}) as mentioned here
Just Add the following in Your ion-view tag
<ion-view cache-view="false">

Angular http interceptors configuration

I am building a project in ionic and I need to send jwt tokens with each request. I am a total angular newbie and I wonder where I need to place the logic for http interceptors. Where should I do that, should I put that inside config part, make a new service or something else?
This is the interceptor logic I need to insert:
$httpProvider.interceptors.push(['$q', '$location', '$localStorage', function ($q, $location, $localStorage) {
return {
'request': function (config) {
config.headers = config.headers || {};
if ($localStorage.token) {
config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
},
'responseError': function (response) {
if (response.status === 401 || response.status === 403) {
$location.path('/signin');
}
return $q.reject(response);
}
};
}]);
This is the config part in my app.js:
.config(function($stateProvider, $urlRouterProvider, $authProvider, ApiEndpoint) {
$authProvider.loginUrl = ApiEndpoint.url + '/authenticate';
$stateProvider
.state('main', {
url: '/main',
abstract: true,
templateUrl: 'templates/main.html'
})
.state('main.auth', {
url: '/auth',
views: {
'content': {
templateUrl: 'templates/login.html',
controller: 'AuthController'
}
}
})
.state('main.front', {
url: '/front',
views: {
'content': {
templateUrl: 'templates/main-front.html',
controller: 'FrontPageController'
}
}
})
.state('main.article', {
url: '/article/{id}',
views: {
'content': {
templateUrl: 'templates/main-article.html',
controller: 'ArticleController'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/main/front');
});
I have added it to services.js like this, I wonder if this is the right approach?
Updated code
services.js
angular.module('coop.services', [])
.factory('ArticleService', function($http, ApiEndpoint) {
return {
all: function() {
return $http.get(ApiEndpoint.url + "/articles/latest").then(function(response){
articles = response.data;
return articles;
});
},
get: function(id) {
return this.all().then(function(response) {
var articles = response;
for (var i in articles) {
if (articles[i].id == id) {
return articles[i];
}
}
return {};
})
}
};
})
.factory('AuthenticationInterceptor', function RequestInterceptor($q, $location, $localStorage, $rootScope, CoreConfig) {
var service = this;
service.request = function (config) {
config.headers = config.headers || {};
if ($localStorage.token) {
config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
};
service.responseError = function (response) {
if (response.status === 401 || response.status === 403) {
$location.path('/signin');
}
return $q.reject(response);
};
return service;
});
.config part in app.js:
.config(function($stateProvider, $urlRouterProvider, $authProvider, ApiEndpoint, $httpProvider) {
$httpProvider.interceptors.push('AuthenticationInterceptor');
$authProvider.loginUrl = ApiEndpoint.url + '/authenticate';
$stateProvider
.state('main', {
url: '/main',
abstract: true,
templateUrl: 'templates/main.html'
})
.state('main.auth', {
url: '/auth',
views: {
'content': {
templateUrl: 'templates/login.html',
controller: 'AuthController'
}
}
})
.state('main.front', {
url: '/front',
views: {
'content': {
templateUrl: 'templates/main-front.html',
controller: 'FrontPageController'
}
}
})
.state('main.article', {
url: '/article/{id}',
views: {
'content': {
templateUrl: 'templates/main-article.html',
controller: 'ArticleController'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/main/front');
});
The Interceptors are usually configured at the bootstrapping phase.
I tend to handle it under the app config:
appName.config(["$httpProvider", ($httpProvider: ng.IHttpProvider) => {
$httpProvider.interceptors.push(() => {
// Your interceptor's logic here
});
});
"An interceptor is simply a factory() service that returns an object with 4 properties that map to functions". So write your interceptor as a normal service with which methods you need overide (request, response, requestError, responseError).
In code example below, I just care to request and respondError property so I just return a service with two propertis. You can also made many interceptors to handle each kind of these property. Many interceptors can be applied to only one property (some kind of interceptor: authentication, handle error, restore request, pre-process response/request data...).
app.factory('AuthenticationInterceptor', function RequestInterceptor($rootScope, CoreConfig) {
var service = this;
service.request = function (config) {
if (angular.isDefined(CoreConfig.TokenKeyString) && angular.isDefined(CoreConfig.SessionKeyString)) {
config.headers['Authorization-Token'] = CoreConfig.TokenKeyString;
config.headers.SessionKeyString = CoreConfig.SessionKeyString;
}
return config;
};
service.responseError = function (response) {
return response;
};
return service;
});
then push your interceptor at config phase:
appp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('AuthenticationInterceptor');
}]);

Middleware type functionality of Laravel in AngularJS?

I am new to AngularJS I have been recently deployed to a AngularJS project. Now at backend I use Laravel and I want to know if there is a way in Angular that I can create or use the same functionality what middleware does in Laravel.
What I basically want is that I need if user is logged in then only he can move forward in the application to other pages.
I have tried something but I don't feel it is correct.
app.controller('afterLogin', function ($scope, $http, $translate,$state,toastr,$auth) {
var init = function () {
var req = {
method: 'GET',
url: baseUrl + 'username',
headers: {
'X-CSRF-TOKEN': token
}
};
$http(req)
.then(function (response) {
if(response.data.name != '')
{
$state.go('app.dashboard');
}
else
{
$state.go('core.login');
}
});
};
// and fire it after definition
init();
$scope.login = function($Login_form) {
var req = {
method: 'POST',
url: baseUrl + 'login/check',
headers: {
'X-CSRF-TOKEN': token
},
data: $scope.user
};
$http(req)
.then(function (response) {
if(response.data.status == 'success')
{
$state.go('app.dashboard');
toastr.success('', 'Logged in successfully');
}else
{
toastr.warning('', response.data.message);
}
});
};
Now the init() does is that it goes to my Laravel controller and checks is user is logged in if not then returns to login page else other wise to dashboard.
I think it is a common problem, I had to solve it too.
Basically you sohuld use the ui-router and then for the states where authentication is needed, you can call an authentication function to proof if the user is logged or not (I also check if it has the roles a to access).
I suggest the use of a service to store the User state.
myApp.config(function($stateProvider, $urlRouterProvider) {
//
// For any unmatched url, redirect to /home
$urlRouterProvider.otherwise("/home");
//
// Now set up the states
$stateProvider
.state('home', {
url: "/home",
templateUrl: "partials/home.html",
controller: 'homeController',
controllerAs: 'homeCtrl'
})
.state('contact', {
url: "/contact",
templateUrl: "partials/contact.html",
controller: 'contactController',
controllerAs: 'contactCtrl'
})
.state('profile', {
url: '/profile',
templateUrl: 'partials/profile.html',
controller: 'profileCtrl',
resolve: {
authenticated: authentic
}
});
function authentic($q, $location, $auth) {
var deferred = $q.defer();
if (!$auth.isAuthenticated()) {
$location.path('/login');
} else {
deferred.resolve();
}
return deferred.promise;
};
});
I hope it helps.

Nested template routes in ui.router

(AngularJS v1.2.28 - angular-ui-router v0.2.13
In my index.html I have the following:
<div class="wrapper" ui-view></div>
In my app.js I have my stateProvider set up as:
$urlRouterProvider.otherwise('/app/search');
$stateProvider.state("app", {
url: '/home',
controller: 'MainCtrl',
templateUrl: 'views/main.html'
}).state('app.search', {
resolve: {
categories: function ($q, $stateParams, LiveOak) {
var deferred = $q.defer();
LiveOak.readMembers('/liveoak/storage/categories', {
success: function (categories) {
deferred.resolve(categories);
},
error: function (error) {
console.error(error);
}
});
return deferred.promise;
}
},
url: '/search',
templateUrl: 'views/search.html',
controller: 'SearchCtrl'
}
).state('app.subjects', {
url: '/subjects/:id',
abstract:true,
templateUrl: '<ui-view/>'
}
).state('app.subjects.default', {
resolve: {
subjects: function ($q, $stateParams, LiveOak) {
var deferred = $q.defer();
var categoryId = $stateParams.id;
var query = {
categoryId : categoryId
};
LiveOak.readMembers('/liveoak/storage/subjects', {
query: query,
success: function (subjects) {
console.log("subjects resolved")
deferred.resolve(subjects);
},
error: function (error) {
console.error(error);
}
});
return deferred.promise;
},
instructors: function ($q, $stateParams, LiveOak) {
}
},
url: '',
templateUrl: 'views/subject.html',
controller: 'SubjectCtrl'
}).state('app.subjects.authors', { //THIS IS NOT RECOGNIZED
resolve: {
authors: function ($q, $stateParams, LiveOak) {
var deferred = $q.defer();
var subjectId = $stateParams.id;
var query = {
query.subjectId : subjectId
};
LiveOak.readMembers('/liveoak/storage/authors', {
query: query,
success: function (authors) {
deferred.resolve(authors);
},
error: function (error) {
console.error(error);
}
}
);
return deferred.promise;
}
},
url: '/subjects/:id/authors/',
templateUrl: '../views/subjects.authors.html',
controller: 'AuthorsCtrl'
}
);
}]);
I am wrestling with the state: app.subjects.authors. Right now app.search and app.subjects work. However, when I try to go the the state: app.subjects.authors it is not even recognized. I set up up a state app.subject as abstract, so hopefully app.subjects.authors wouldn't be overridden by app.subjects. Anyone see anything out of the ordinary?
Thanks for the help!!
My subject.html looks like this:
<div ng-repeat="subject in subjects" class="mdl-cell mdl-cell--4-col">
<a href="#/app/subjects/{{subject.categoryId}}/authors">
<span>{{subject.name}}</span>
</a>
</div>
Just change templateUrl: to template:. You don't need abstract:.
.state('app.subjects', {
url: '/subjects/:id',
template: '<ui-view/>'
})
You shall have:
url: '/authors',
Instead of:
url: '/subjects/:id/authors/',
Because url is relative. So the url of child state is continuation of parent state's url. So authors state will match following url:
/home/subjects/:id/authors

Resources