I have this $location.path redirection:
myapp.controller('registerCtrl', function ($scope, $location, regService) {
$scope.register = function() {
$('#regbutton').prop('disabled','disabled');
regService.createUser($scope.email, $scope.password, function(id) {
if (id) {
$('#register').modal('hide');
$location.path('/account');
}
});
}
})
When the redirection occurs it redirects the user to http://myapp.com/#/account
Now I want to display a different template to show the user account. So I'm trying to use ngRoute but cannot get it to work properly..
myapp.config(['$routeProvider', '$locationProvider', '$provide',
function ($routeProvider, $locationProvider, $provide) {
console.log('in');
$provide.decorator('$sniffer', function($delegate) {
$delegate.history = false;
return $delegate;
});
$routeProvider.
when('/account', {
templateUrl: 'account.html',
resolve: {
// I will cause a 1 second delay
delay: function ($q, $timeout) {
console.log('in resolve');
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
});
$locationProvider
.html5Mode(true)
.hashPrefix('');
}]);
The route you should be using in the configuration when() function is /account
Related
Issue: On Firebase login, I would like to redirect the user to a new page.I am trying to use $location.path() in my controller even I tried using $state.go(). But it seems to be no use. Also I am not getting any error in console.
Using Firebase signInWithEmailAndPassword method, Angularjs 1.5, ui-router and AngularFire.
login.service.js
var firebaseAuthObject = fbDbConn.auth();
function login(emailid, passwd) {
return firebaseAuthObject.signInWithEmailAndPassword(emailid, passwd);
}
login.controller.js
(function() {
'use strict';
angular
.controller('AuthController', AuthController);
AuthController.$inject = ['$scope', '$location', 'authService'];
function AuthController($scope, $location, authService) {
$scope.message = null;
$scope.error = null;
$scope.register = function() {
return authService.register($scope.email, $scope.password)
.then(function(userData) {
$scope.message = "User created with uid: " + userData.uid;
}).catch(function(error) {
$scope.error = error;console.log(error);
});
};
$scope.login = function() {
$scope.auth_error ="";
return authService.login($scope.email, $scope.password)
.then(function(authData) {
$location.path('/app/overview'); //$state.go('/app/overview');
}).catch(function(error) {console.log(error);
$scope.error = error;
$scope.auth_error = "Username or Password is wrong.";
});
};
$scope.logout = function() {console.clear();
authService.logout();
$location.path('/login');
};
}
})();
config.route.js
(function() {
'use strict';
angular
.module('singApp.login', ['ui.router','firebase'])
.config(configFunction)
.run(runFunction);
configFunction.$inject = ['$stateProvider'];
function configFunction($stateProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'app/modules/login/login.html'
})
}
runFunction.$inject = ['$location', 'authService', 'firebaseDataService', 'PROTECTED_PATHS'];
function runFunction($location, authService, firebaseDataService, PROTECTED_PATHS) {
authService.firebaseAuthObject.onAuthStateChanged(function(authData) {
if (!authData && pathIsProtected($location.path())) {
authService.logout();
$location.path('/login');
};
});
function pathIsProtected(path) {
return PROTECTED_PATHS.indexOf(path) !== -1;
}
}
})();
Thanks for help !!
first you should inject $state to your controller and use $state.go('stateName')
$state.go('/app/overview') will not work
you should use $state.go('stateName')
angular
.controller('AuthController', AuthController);
AuthController.$inject = ['$scope', '$location','$state', 'authService'];
function AuthController($scope, $location, $state,authService) {
$scope.message = null;
$scope.error = null;
$scope.register = function() {
return authService.register($scope.email, $scope.password)
.then(function(userData) {
$scope.message = "User created with uid: " + userData.uid;
}).catch(function(error) {
$scope.error = error;console.log(error);
});
};
$scope.login = function() {
$scope.auth_error ="";
return authService.login($scope.email, $scope.password)
.then(function(authData) {
$state.go('stateName');
}).catch(function(error) {console.log(error);
$scope.error = error;
$scope.auth_error = "Username or Password is wrong.";
});
};
$scope.logout = function() {console.clear();
authService.logout();
$location.path('/login');
};
}
})();
Just check the $state.go() method instead of $location
First inject the dependency '$state'
AuthController.$inject = ['$scope', '$state', 'authService'];
Check your routes.js file.
The below is a sample code.
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/profile");
$stateProvider
.state('login', {
url: '/',
templateUrl: 'login.html'
})
.state('app.overview', {
url: '/overview',
templateUrl: 'views/overview.html'
})
});
If everything correct then then you can use the below code for redirection.
$state.go('login');
I'm using the '$stateChangeSuccess' event to find out the route changes.
app.run(['$rootScope', '$state', '$stateParams', '$cookies', '$timeout',
function($rootScope, $state, $stateParams, $cookies, $timeout) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeSuccess', function(event, nextRoute, toState) {
console.log(nextRoute.name);
// $state.go('login');
});
}
])
Right now i am making an AngularJS+UI router install application. But i have a problem, the problem is, that i want to disable access to the views, associated with the install application. I want to do it in resolve in the state config.
But the problem is i need to get the data from a RESTful API, whether the application is installed or not. I tried making the function, but it loaded the state before the $http.get request was finished.
Here was my code for the resolve function:
(function() {
var app = angular.module('states', []);
app.run(['$rootScope', '$http', function($rootScope, $http) {
$rootScope.$on('$stateChangeStart', function() {
$http.get('/api/v1/getSetupStatus').success(function(res) {
$rootScope.setupdb = res.db_setup;
$rootScope.setupuser = res.user_setup;
});
});
}]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/404");
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
data: function($q, $state, $timeout, $rootScope) {
var setupStatus = $rootScope.setupdb;
var deferred = $q.defer();
$timeout(function() {
if (setupStatus === true) {
$state.go('setup-done');
deferred.reject();
} else {
deferred.resolve();
}
});
return deferred.promise;
}
}
})
.state('user-registration', {
url: "/install/user-registration",
templateUrl: "admin/js/partials/user-registration.html",
controller: "RegisterController"
})
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html"
})
.state('404', {
url: "/404",
templateUrl: "admin/js/partials/404.html"
});
}]);
})();
EDIT:
Here is what my ajax call returns:
Try this way:
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
setupStatus: function($q, $state, $http) {
return $http.get('/api/v1/getSetupStatus').then(function(res) {
if (res.db_setup === true) {
$state.go('setup-done');
return $q.reject();
}
return res;
});
}
}
})
Then inject setupStatus in controller:
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html",
controller: ['$scope', 'setupStatus', function ($scope, setupStatus) {
$scope.setupdb = setupStatus.db_setup;
$scope.setupuser = setupStatus.user_setup;
}]
})
This question comes from another one: AngularJS - Determine if the view should be displayed by an ajax call result upon the route changes
As to my previous question, finally I came to this solution:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", checkLoginController);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider'];
function routeConfigurator($routeProvider, $locationProvider) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", function checkPermit($q, userFactory, $location) {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({
message: "Proceed to change route."
});
}
else {
deferred.reject({
message: "Redirect to the default page."
});
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}]
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", function checkPermit($q, userFactory, $location) {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({
message: "Proceed to change route."
});
}
else {
deferred.reject({
message: "Redirect to the default page."
});
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}]
}
});
// ...
}
})();
However, I have repeated the same piece of code for each route I would like to forbid undesired access. So now my question is how to do it once for all. I have tried the code as below:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", checkLoginController);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider'];
function routeConfigurator($routeProvider, $locationProvider) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", checkPermit]
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", checkPermit]
}
});
// ...
}
function checkPermit($q, userFactory, $location) {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({
message: "Proceed to change route."
});
}
else {
deferred.reject({
message: "Redirect to the default page."
});
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}
})();
And it doesn't work, I got error saying: defer is not defined, something like that. Then I used a factory to wrap that piece of logic:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", checkLoginController)
.factory('checkPermit', checkPermitFactory);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider', 'checkPermit'];
checkPermitFactory.$inject = ['$q', '$location', 'userFactory'];
function routeConfigurator($routeProvider, $locationProvider, checkPermit) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
// ...
}
function checkPermitFactory($q, userFactory, $location) {
function checklogin() {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({ message: "Proceed to change route." });
}
else {
deferred.reject({ message: "Redirect to the default page." });
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}
var factory = {
checklogin: checklogin
};
return factory;
}
})();
And I got error saying that it could not find checkPermit provider, when investigating this problem, I realized that you just cannot inject an dependency on an stance of factory to routeConfigurator, so here I am supposed to use checkPermitProvider instead.
I am confused now.
Any help is appreciated. Thanks.
thank you all for the replies.
In the end, I found I can get it working in this way:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", ['$q', '$location', 'userFactory', function checkPermitFactory($q, userFactory, $location) {
function checklogin() {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({ message: "Proceed to change route." });
}
else {
deferred.reject({ message: "Redirect to the default page." });
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}
var factory = {
checklogin: checklogin
};
return factory;
}])
.factory('checkPermit', checkPermitFactory);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider', 'checkPermit'];
function routeConfigurator($routeProvider, $locationProvider, checkPermit) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
// ...
}
})();
I used $inject property to specify the dependencies just because that was suggested in the section 'Manually Identify Dependencies' in this article: https://github.com/johnpapa/angularjs-styleguide#manually-identify-dependencies.
And honestly I don't quite understand how does $inject work exactly though; I just got the concerns behind that. So this problem has been solved, but I don't know the difference between the two ways of defining a controller and declaring there dependencies.
I would like to before the advent of the home page if the user is not logged in is to move it to the login page.
At this moment Main page appears (half a second) and then loads the login page.
var app = angular.module("app", ["ngRoute", "ngAnimate"])
.constant('ACCESS_LEVELS', {
guest: 1,
user: 2,
admin: 3
});
app.config(["$routeProvider", "$locationProvider", "ACCESS_LEVELS", function($routeProvider, $locationProvider, ACCESS_LEVELS) {
$routeProvider
.when("/", {
template: "",
access_level: ACCESS_LEVELS.user
});
}]);
app.run(["$rootScope", "$window", "LoginService", function($rootScope, $window, LoginService) {
$rootScope.$on('$routeChangeStart', function(evt, next, curr) {
if(next.access_level !== undefined) {
LoginService.checkSession().then(function(response) {
$rootScope.isLoggedIn = response;
if(!response) {
$window.location.href = '/login.html';
}
}, function(error) {
$rootScope.isLoggedIn = error;
});
}
})
}]);
Is there a way to angular done without flash home page?
regards
You can use the ‘resolve’ property of the routeProvider.
From the docs:
resolve - 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.
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
So your routeProvider could look as follows, with the session promise specified as a dependency of your home route. You would then need to inject the session into the home controller.
$routeProvider
.when("/", {
template: "",
access_level: ACCESS_LEVELS.user,
controller: ‘homeCtrl’,
resolve: {
session: function(LoginService) {
return LoginService.checkSession();
}
}
});
A good blog post: http://blog.brunoscopelliti.com/show-route-only-after-all-promises-are-resolved
My current code:
in main app.js:
var app = angular.module("app", ["ngRoute", "ngAnimate", "ngResource"])
.constant('ACCESS_LEVELS', {
guest: 1,
user: 2,
admin: 3
});
besecure.config(["$routeProvider", "$locationProvider", "ACCESS_LEVELS", function($routeProvider, $locationProvider, ACCESS_LEVELS) {
$routeProvider
.when("/", {
template: "",
label: "Home",
access_level: ACCESS_LEVELS.user,
resolve: {
session: function(LoginService) {
return LoginService.checkSession();
}
}
});
}]);
app.run(["$rootScope", "$window", "$location", "LoginService", function($rootScope, $window, $location, LoginService) {
$rootScope.loadingView = false;
$rootScope.$on('$routeChangeStart', function(evt, curr, prev) {
if(curr.access_level !== undefined) {
if(curr.$$route && curr.$$route.resolve) {
$rootScope.loadingView = true;
} else {
$window.location.href = '/login.html';
}
}
})
}]);
Service:
app.factory("LoginService", function($resource, $q) {
var LoginService,
Login = $resource("/auth/login");
LoginService = {
checkSession: function() {
var deferred = $q.defer();
Login.get().$promise.then(function(response) {
deferred.resolve(response.result);
}, function(error) {
deferred.reject(false);
});
return deferred.promise;
}
};
return LoginService;
});
Service is OK.
and not work redirecting
I'm facing an issue. I'm working with angular 1.2RC3 and ui-route 0.2.
If i resolve with a function which is doing a synchronous return, it works.
With a promise, the controller is initialized before resolving the promise.
http://plnkr.co/edit/feXHNaGsXwpXDBXkxLZx
angular.module('srcApp', ['ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
var userResult = {
id : 'userid',
displayName : 'displayName'
};
var getUserPromise = function ($q, $timeout, $log) {
var defer = $q.defer;
$timeout(function () {
$log.log('promise resolved');
defer.resolve(userResult);
}, 2000);
return defer.promise;
};
$stateProvider.state('test', {
url: '/',
template: '<div>{{user.displayName}}</div>',
controller: 'testCtrl',
resolve : {
user: getUserPromise
}
});
});
var testCtrl = angular.module('srcApp').controller('testCtrl', function ($scope, $http, $log, user) {
$log.log("test controller init");
$log.log("test controller user=" + user);
$scope.user = user;
});
Weird... It's pretty much what I do line for line in an app.
Solved: http://plnkr.co/edit/oC5wK8aDcq82mWl8ES6l?p=preview
You typed:
$q.defer
instead of:
$q.defer()