I have an angular app with a login page and a signup page and a dashboard that a user is able to access once they have logged in. Currently a user can you directly to the login page or the signup page, so I have a ng-app at the top of both pages. But this does not seem the right way to do things, and it doesn't make sense to initialize my app more than once. But if I only have the ng-app on the login page and a user goes directly to the signup page, the app wont be initialized and I wont have access to the controller for my signup page. How can I get around this?
I would like to just initialize my app once as from what I have read this is how it should be done.
Thank you
Put the ng-app in an index.html file, then have something like this in the body:
<body>
<div data-ui-view></div>
</body>
Then you can use ui-router or ng-route to switch 'states' (ie login, signup etc) and the 'view' will fill into the data-ui-view. Personally I find ui-router to be better, but either can do it.
Most of the time you have to use ng-app once per application. You can manage views using ngRoute module or with ui-router and you can find more options on it.
See example below, there are some extra things you can learn from.
angular.module('demoApp', ['ui.router'])
.run(function($rootScope, $state) {
$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
if (error.redirectTo) {
$state.go(error.redirectTo);
} else {
$state.go('error', {status: error.status})
}
})
})
.factory('userService', userService)
.config(routes);
function userService() {
var usersMock = {
'testUser': {
username: 'testUser',
password: '1234'
},
'testUser2': {
username: 'testUser2',
password: '1234'
}
};
var userService = {
user: undefined,
login: function(userCredentials) {
// later --> $http.post('auth', userCredentials).then(...)
// for demo use local data
var user = usersMock[userCredentials.username]
userService.user = ( user && ( user.password == userCredentials.password ) ) ?
user : undefined;
return user;
},
logout: function() {
userService.user = undefined;
}
}
return userService;
}
function routes($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('root', {
url: '',
abstract:true,
resolve: {
'user': function(userService) {
return userService.user; // would be async in a real app
}
},
views: {
'': {
templateUrl: 'layout.html',
},
'header#root': {
template: '<h1>header View<span ng-if="user"><button ng-click="logout()">logout</button></span><span ng-if="!user"><button ng-click="login()">login</button></span></h1>',
controller: function($scope, $state, user, userService) {
$scope.user = user;
$scope.login = function() {
$state.go('login');
};
$scope.logout = function() {
userService.logout();
$state.go('root.home', {}, {reload: true});
};
}
},
'footer#root': {
template: '<p>footer view</p>'
}
}
})
.state('root.home', {
url: '/',
views: {
'content': {
template: 'Hello at home'
}
}
})
.state('root.about', {
url: '/about',
views: {
'content': {
template: 'about view'
}
}
})
.state('root.restricted', {
url: '/restricted',
resolve: {
auth: function(userService, $q, $timeout) {
var deferred = $q.defer();
/* //with an async
return UserService.load().then(function(user){
if (permissionService.can(user, {goTo: state})) {
return deferred.resolve({});
} else {
return deferred.reject({redirectTo: 'some_other_state'});
}
}*/
$timeout(function() {
if ( angular.isUndefined(userService.user) ) {
return deferred.reject({redirectTo: 'login'});
}
else {
return deferred.resolve(userService.user);
}
});
return deferred.promise;
}
},
views: {
'content': {
template: 'this is only visible after login. Hello {{user}}!',
controller: function($scope, auth) {
$scope.user = auth.username;
}
}
}
})
.state('login', {
url: '/login',
templateUrl: 'views/login.html',
controller: function($scope, $state, userService) {
$scope.login = function(cred) {
var user = userService.login(cred);
if (angular.isUndefined(user)) {
alert('username or password incorrect.')
}
else {
$state.go('root.restricted');
}
};
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<div ng-app="demoApp">
<a ui-sref="root.home" href="#">home</a>
<a ui-sref="root.about" href="#">about</a>
<a ui-sref="root.restricted" href="#">restricted page</a>
<div ui-view>
</div>
<script type="text/ng-template" id="views/login.html">
<h1>Login</h1>
<label>Username</label><input ng-model="userCred.username"/>
<label>Password</label><input type="password" ng-model="userCred.password"/>
<button ng-click="login(userCred)">login</button>
</script>
<script type="text/ng-template" id="layout.html">
<div>
<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>
</div>
</script>
</div>
Related
Not getting redirected to login page my profile page is an html and main is the login page. I tried redirecting it to both the pages but it keeps going to the catch block as soon as a relocation is provided.
angular.module('meanhotel').controller('RegisterController', RegisterController);
function RegisterController($http) {
var vm = this;
vm.register = function() {
var user = {
firstname: vm.firstname,
lastname: vm.lastname,
email: vm.email,
password: vm.password
};
if (!vm.email || !vm.password) {
vm.error = 'Please add email and password.';
} else {
if (vm.password !== vm.passwordRepeat) {
vm.error = 'Please make sure the passwords match.';
} else {
$http.post('/api/users/register', user).then(function(result) {
console.log(result);
// vm.message = 'Successful registration, please login!';
vm.error = '';
// $window.location.href('/main');
//$location.path('#!/profile');
$window.location.href = '/main.html';
}).catch(function(error) {
vm.error = "User already exists";
console.log(error);
});
}
}
}
};
app.js:
routing in app.js is as follows. Profile is a simple html page with a logout button. not sure if the user is getting passed to it as well. I am setting the user in another controller.
angular.module('meanhotel', ['ngRoute', 'angular-jwt']).config(config).run(run);
function config($httpProvider, $routeProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
$routeProvider
.when('/', {
templateUrl: 'angular-app/main/main.html',
access: {
restricted: false
}
})
.when('/register', {
templateUrl: 'angular-app/register/register.html',
controller: RegisterController,
controllerAs: 'vm',
access: {
restricted: false
}
})
.when('/profile', {
templateUrl: 'angular-app/profile/profile.html',
controller: LoginController,
controllerAs: 'vm',
access: {
restricted: true
}
})
.otherwise({
redirectTo: '/'
});
}
appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.hashPrefix("");
}]);
function run($rootScope, $location, $window, AuthFactory) {
$rootScope.$on('$routeChangeStart', function(event, nextRoute, currentRoute) {
if (nextRoute.access !== undefined && nextRoute.access.restricted && !$window.sessionStorage.token && !AuthFactory.isLoggedIn) {
event.preventDefault();
$location.path('/');
}
});
}
Can you try once using
$location.path('/profile');
I'm new IONIC & AngularJS. Currently, working on an app & stuck at a point. Don't how to resolve the issue.
I've a login form. After user login to the app, he/she will land at HOME page. In the home page, I've an image. On that image, i'm using ng-click. So, on click of that image, it'll redirect the user to some other page. Here I'm facing the issue & the issue is just after login when I'm coming to the home page, on click of that image ng-click is not working at all. But, once I refresh the browser & click on that image ng-click start working. Don't know why this wired thing is happening.
Here are all files which I'm using. The ionic version which I'm using in 1.7.12
app.js
(function(){
var app = angular.module('e2pro', ['ionic', 'e2pro.LoginController', 'e2pro.HomeController', 'e2pro.AttendanceController', 'e2pro.LogoutController','e2pro.MenuController','e2pro.EmpProfileController','e2pro.EmpSearchController', 'e2pro.VendorController', 'ngMessages', 'ngCordova', 'angularMoment']);
var requestToken = "";
var accessToken = "";
var deviceToken = null;
var access_token = null;
var refresh_token = null;
var session_id = null;
var user_id = null;
var user_login_type = null;
var route_to = null;
app.run(function($ionicPlatform, RequestsService, GeoAlert) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
console.log('inside app.run function');
});
});
// Service for logout user from app
app.factory("User", function($http, $q, $rootScope, $ionicHistory, $state) {
return {
logout: function(){
window.localStorage.clear();
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
$ionicHistory.nextViewOptions({ disableBack: true, historyRoot: true });
$state.go("login");
}
}
});
app.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'MenuController'
})
.state('app.tabs', {
url: "/tabs",
views: {
'menuContent': {
templateUrl: "templates/tabs.html",
}
}
})
.state('login', {
url: "/login",
templateUrl: "templates/login.html",
//controller: 'LoginController'
})
.state('markEmpAttendance', {
url: "/markEmpAttendance",
templateUrl: "templates/attendance/markEmpAttendance.html",
//controller: 'AttendanceController'
})
.state('app.tabs.home', {
url: '/home',
views: {
'home-tab': {
templateUrl: 'templates/home.html',
}
}
})
.state('app.tabs.emp-profile', {
url: '/emp-profile/:empId',
views: {
'home-tab': {
templateUrl: 'templates/empProfile.html',
//controller: 'EmpProfileController'
}
}
})
.state('app.tabs.vendor', {
url: '/vendor',
views: {
'home-tab': {
templateUrl: 'templates/vendor/vendor.html',
//controller: 'EmpProfileController'
}
}
})
.state('app.tabs.emp-search', {
url: '/emp-search',
views: {
'home-tab': {
templateUrl: 'templates/empSearch.html',
//controller: 'EmpProfileController'
}
}
})
.state('app.tabs.service-request', {
url: "/articles",
views: {
'serviceRequest-tab': {
templateUrl: "templates/serviceRequest.html",
controller: 'articlesCtrl'
}
}
})
.state('app.tabs.colonies', {
url: "/colonies",
views: {
'colonies-tab': {
templateUrl: "templates/colonies.html",
controller: 'coloniesCtrl'
}
}
})
.state('app.foo', {
url: "/foo",
views: {
'menuContent': {
templateUrl: "templates/foo.html",
controller: 'fooCtrl'
}
}
});
$urlRouterProvider.otherwise('/app/tabs/home');
$httpProvider.interceptors.push('sessionInjector');
});
}());
login.js (controller file)
angular.module('e2pro.LoginController', [])
// Employee Attendance Controller
.controller('LoginController', function($http, $scope, $state, $ionicHistory, $ionicLoading, $cordovaOauth, RequestsService){
console.log('Inside Login Controller');
var baseUrl=null;
$scope.credentials = {};
$scope.validationFailed = false;
$http.get('js/config.json')
.then(function(res){
baseUrl = res.data.server[res.data.mode];
});
// Method for user's default login
$scope.validateCredentials = function(form){
console.log('Form Validation start for login : '+form.$valid);
var attendance_require = null;
var emp_attendance_status = null;
// Setting module data element for the api request
$scope.credentials.module = 'user_login';
$scope.credentials.pageId = 1548;
// Check form validation status & move control accordingly
if(!form.$valid)
{
return false;
}
// Show spinner animation
$ionicLoading.show({
template: '<ion-spinner icon="android"></ion-spinner>'
});
$http({
method: 'POST',
url: baseUrl+'/S/E2Pro_MobileApiEndPoint.php',
data : $scope.credentials
}).then(function successCallback(response) {
if(response['data']['status'] === 'success')
{
session_id = response['data']['data']['session_id'];
user_id = response['data']['data']['user_id'];
route_to = response['data']['data']['route_to'];
attendance_require = response['data']['data']['attendance_require'];
emp_attendance_status = response['data']['data']['emp_attendance_status'];
window.localStorage.setItem("session_id", session_id);
window.localStorage.setItem("user_id", user_id);
window.localStorage.setItem("user_login_type", 'default');
// Hide Spinner before redirecting to home page
$ionicLoading.hide();
// Redirecting to home page
if(route_to === 'home'){
$state.go('app.tabs.home');
return false;
}
}
else
{
// Hide Spinner before redirecting to home page
$ionicLoading.hide();
// Show message for email id & password miss match
$scope.validationFailed = true;
}
}, function errorCallback(response) {
// console.log('Error occcur during user authentication');
// Hide Spinner before redirecting to home page
$ionicLoading.hide();
});
};
});
Home.js (Controller file)
angular.module('e2pro.HomeController', [])
// Employee Attendance Controller
.controller('HomeController', function($scope, $state, $location, $ionicHistory, $ionicSideMenuDelegate, $http, $ionicPopup, User, GeoAlert){
console.log('Inside Home Controller');
var baseUrl=null;
// Check application session. If it's found not exist redirect user to login page
if(window.localStorage.getItem("session_id") === "undefined" || window.localStorage.getItem("session_id") === null) {
$ionicHistory.nextViewOptions({
disableAnimate: true,
disableBack: true
});
$state.go("login");
return false;
}
$scope.empName = '';
$scope.alertMsgBox = false;
$scope.alertMsgText = '';
$scope.employees = [];
$http.get('js/config.json')
.then(function(res){
baseUrl = res.data.server[res.data.mode];
});
// Method for showing Vendor page
$scope.showVendorPage = function(){
console.log('Clicked on vendor icon');
$state.go('app.tabs.vendor');
}
});
Home.html (template file)
<ion-view view-title="Home">
<ion-content class="has-tabs">
<div ng-controller='HomeController' >
<div class="row" style="margin-top:15px;">
<div class="col">
<img src="img/leave.png" ng-click="showVendorPage()">
<h5>Vendor</h5>
</div>
<div class="col">.col</div>
<div class="col">.col</div>
</div>
</div>
</ion-content>
</ion-view>
My problem is quite specific so I haven't been able to find an answer for this particular scenario anywhere, I did manage to get the functionality I require but would like to know if there is a better way of doing it. I will start by explaining the problem.
In index.html I have the following:
<html>
...
<lumx-navbar></lumx-navbar>
<div class="wrap">
<div ui-view></div>
</div>
...
</html>
lumxnavbar is a directive for the navigation bar of the application
nav.js
module.exports = function(appModule) {
appModule.directive('lumxNavbar', function(UserFactory, $window, $rootScope) {
return {
template: require('./nav.html'),
controller: function($scope) {
$scope.nav = require('../../static-data/nav.json');
$scope.user = $rootScope.user;
$scope.logout = function() {
UserFactory.logout();
$scope.user = '';
$window.location.href = '/#/login';
};
}
};
});
};
nav.html
<header>
...
<span ng-show="user" class="main-nav--version">Logged in as: {{user}}</span>
...
</header>
So the application starts with a login page at which point there is no user variable available anywhere. Once the user logs in there will be a user returned from a service.
my routes look like this (I am using angular-ui-router)
$stateProvider
.state('anon', {
abstact: true,
template: '<ui-view/>',
data: {
access: false
}
})
.state('anon.login', {
url: '/login',
template: require('../views/login.html'),
controller: 'LoginCtrl'
});
$stateProvider
.state('user', {
abstract: true,
template: '<ui-view/>',
data: {
access: true
}
})
.state('user.home', {
url: '/home',
template: require('../views/home.html'),
controller: 'HomeCtrl'
})
...
so the idea is that once the user logs in the navbar will change from
to this:
the only way I have found to accomplish this reliably is to do the following
instantiate a variable in $rootScope
appModule.run(function($rootScope, $location, UserFactory, $state) {
$rootScope.user = UserFactory.getUser();
...
then set the same variable from the login controller
...
$scope.login = function (username, password) {
UserFactory.login(username, password).then(function success(response) {
$rootScope.user = response.data.user.username;
$state.go('user.home');
}, handleError);
};
...
so this will update the navbar because of this line in the directive $scope.user = $rootScope.user; but my question is whether there is a better way of doing this without using $rootScope or would this be a suitable use for it?
Any input would be appreciated...:)
I have following routing with athentication, which is done via a PHP-Script and MySQL:
app.config
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/login', {
title: 'Login',
templateUrl: 'partials/login.html',
controller: 'authCtrl'
})
.when('/logout', {
title: 'Logout',
templateUrl: 'partials/login.html',
controller: 'logoutCtrl'
})
.when('/dashboard', {
title: 'Dashboard',
templateUrl: 'partials/dashboard.html',
controller: 'authCtrl'
})
.otherwise({
redirectTo: '/login'
});
}])
.run(function ($rootScope, $location, Data) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
$rootScope.authenticated = false;
Data.get('session').then(function (results) {
if (results.uid) {
$rootScope.authenticated = true;
$rootScope.uid = results.uid;
$rootScope.name = results.name;
$rootScope.email = results.email;
} else {
var nextUrl = next.$$route.originalPath;
if (nextUrl == '/signup' || nextUrl == '/login') {
} else {
$location.path("/login");
}
}
});
});
});
authCtrl
app.controller('authCtrl', function ($scope, $rootScope, $routeParams, $location, $http, Data) {
$scope.login = {};
$scope.signup = {};
$scope.doLogin = function (customer) {
Data.post('login', {
customer: customer
}).then(function (results) {
Data.toast(results);
if (results.status == "success") {
$location.path('dashboard');
}
});
};
$scope.logout = function () {
Data.get('logout').then(function (results) {
Data.toast(results);
$location.path('login');
});
}
});
Now I want to change the navigation depending on the login-status. If user is logged in there should bei a logOUT-Button and a link to the dashboard. If the user isn't logged in it should look like this
sample for unlogged-in user
<header id="navigation">
<nav id="main">
<ul>
<li id="login"><i class="fa fa-power-off"></i> Login</li>
</ul>
</nav>
</header>
<main ng-view>
Content goes here
</main>
What is the best way for creating the navigation? Should it be a seperate template?
When things get complex, I'd rather use ui-router or maybe angular new router (haven't try this one yet) since they support multiple views in the same page. Thus nav becomes its own view, content its own view, etc. And to communicate between the views I'll use message passing with data in either $rootScope or some kind of shared state service.
So something like this... in the beginning, the login shared state is set to logged out. As the last part of login functionality, I'd set the login shared state and set it to logged in. Like I said, I rather make this a shared state service call since I can have it to also do $rootScope.$broadcast some sort of onLoginStateChange and pass the new value there.
Then I'd set up my nav view to listen to this onLoginStateChange using $scope.$on and set its internal view model state in its controller and bind that to ng-if directive so it will display Login if false, or Logout if true (logged in).
I am trying to create a login script using Angularjs. I have an Authentication Service that handles the logic for that.
Here the service:
.factory("AuthSvc",
['$http','$q','$state',
function ($http,$q,$state) {
function GetUser() {
var d = $q.defer();
$http.get('api/auth/check')
.success(function(res){
d.resolve(res);
});
return d.promise;
};
return {
login: function (credentials, form) {
var defer = $q.defer();
$http.post('/api/auth/login', credentials)
.success(function (response) {
form.$setPristine();
user = response;
$state.go('base.posts.content');
defer.resolve();
})
.error(function (response) {
defer.reject();
});
return defer.promise;
},
isLoggedIn: GetUser,
user: null
};
}]);
I have a resolve property and a listener for the user property to update the view on the app configuration as below:
.config(['$stateProvider',
function ($stateProvider) {
// Now set up the states
$stateProvider
.state('base', {
url : "",
templateUrl: "/templates/base/index.html",
resolve : {user : ["AuthSvc",
function(AuthSvc) {
return AuthSvc.user;
}]
},
})
.state('base.login', {
url : "login",
templateUrl: "/templates/login/index.html",
controller : 'LoginCtrl'
})
.state('base.posts', {
abstract : true,
url : 'posts',
templateUrl: '/templates/posts/posts.html'
})
.state('base.posts.content',{
url: '',
resolve: {
posts: function (PostsSvc) {
return PostsSvc.getPosts();
}
},
views:{
'create': {
templateUrl: '/templates/posts/create.html',
controller: 'PostsCtrl'
},
'list': {
templateUrl: '/templates/posts/list.html',
controller: 'PostsCtrl'
}
}
});
}]);
app.run(['$rootScope','AuthSvc','$state',
function ($rootScope,AuthSvc,$state,
) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeStart',
function(event, next, current){
AuthSvc.user = AuthSvc.isLoggedIn();
});
$state.transitionTo('base.posts.content');
}]);
}());
The $rootScope.on('$stateChangeStart') is not working. I see some code where people directly assign a value to a promise without using the then function of the promise. How do I accomplish this using this code?