Manually changing the URL does not call the controller in AngularJS - angularjs

I have a application with main pages as app.html and my controller is app.js. The following is the code in app.js:
angular.module(constants.MODULE_NAME).controller('AppCtrl', function ($scope, $state, $log, $http) {
$scope.role = '';
$http.get("htttp://localhost:8082/service/getUserRole")
.then(function (response) {
$scope.role = response.data.context;
debugger;
if ($scope.role.toLowerCase() == "hr") {
//direct view to hr dashboard
$state.go("app.hr");
} else if($scope.context.toLowerCase() == "eemployee"){
//direct view to employee dashboard
$state.go("app.employee");
}
else{
//do nothing
$state.go("app");
}});
});
So when I run this website the controller is called and based on the value of role the respective dashboard is displayed.When the website runs it hits http://localhost:9080/#/ which is calling the above controller and redirects too http://localhost:9080/#/hr/dashboard (or) http://localhost:9080/#/employee/dashboard.
I have the following in my router.js
export default ['$stateProvider', '$urlRouterProvider', ($stateProvider, $urlRouterProvider) => {
$stateProvider
.state('app', {
url: '/',
template: require('./app.html'),
controller: 'AppCtrl',
controllerAs: 'app'
})
.state('app.hr', {
url: 'hr/dashboard',
template: require('./hr/dashboard/index.html'),
controller: 'HRCtrl',
controllerAs: 'hrctrl'
})
.state('app.employee', {
url: 'employee/dashboard',
template: require('./employee/dashboard/index.html'),
controller: 'EMPCtrl',
controllerAs: 'empctrl'
});
$urlRouterProvider.otherwise('/');
}];
Now when I change the URL to http://localhost:9080/#/ and hit enter then the controller is not getting called. But when I do a refresh the controller gets called. Can I know how I can fix this issue.

Related

$state.go does not change url but redirect to that particular page

I am unable to change my Url using $state.go but i am getting that page for which i have requested in $state.go , I have also used route.js
angular.module("myApp")
.controller('myController', ['$scope','$state', function ($scope, $state) {
$scope.showDetails = function(data){
if(some true condition){
$state.go("create.preemp");
}
else if(some true condition){
$state.go("create.prepolicy");
}
}
}])
angular.module("myApp")
.config(function ($stateProvider, $routeProvider, $urlRouterProvider) {
$stateProvider
.state('signin', {
url: '/',
templateUrl: 'signin/signin.html',
controller: 'signinController'
})
.state('create.preemp', {
url: '/create.preemp',
templateUrl: 'preemp.html',
controller: 'preempController'
})
.state('create.prepolicy', {
url: '/create.prepolicy',
templateUrl: 'prepolicy.html',
controller: 'prepolicyController'
})
$urlRouterProvider.otherwise('/');
})
??

Separate nav from ng-view

I'm brand new to Angularjs and am trying to set up a new site but I'm confused as to the set up. I have a module and am using $route to successfully navigate but I'm lost as to what to do with my nav. When I load the module I want to read my database for a list of links that the user is allowed to access then spit them out in the nav. I don't want to repeat this in every view because I don't need to. So I'm trying to figure out how to run the ajax call once and then keep changing the view (I'd also like to add a class .selected to whatever view they're on). How would I go about doing that, with a directive?
(function () {
var app = angular.module('manage', ['ngRoute', 'manageControllers']);
/*
I've tried this but obviously $http isn't injected. Can I even do that?
var thisApp = this;
$http.get('/test/angular/php/angular.php', {params: {'function': 'nav'}}).then(function successCallback(response) {
});
*/
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
}).
when('/inventory/', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
when('/inventory/:mvKey', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
when('/inventory/:mvKey/:tab', {
templateUrl: 'templates/inventory.html',
controller: 'InventoryCtrl'
}).
/* etc...*/
}
]);
})();
EDIT:
My attempt at getting the nav to run once
controllers.js
var manageControllers = angular.module('manageControllers', []);
var thisApp = this;
nav = null;
navSelected = '/';
manageControllers.controller('NavCtrl', ['$scope', '$http', function($scope, $http) {
if (thisApp.nav === null) {
$http.get('php/angular.php', {params: {'function': 'nav'}}).then(function successCallback(response) {
console.log(response.data);
thisApp.nav = response.data;
$scope.nav = thisApp.nav;
$scope.select = thisApp.navSelected;
});
} else {
$scope.nav = thisApp.nav;
$scope.select = thisApp.navSelected;
}
}]);
manageControllers.controller('DashCtrl', ['$scope', function($scope) {
thisApp.navSelected = '/';
}]);
I would swith to UI Router (https://github.com/angular-ui/ui-router) instead of $route. It allows you being much more flexible with your routing.
A Small example:
app.config(['$stateProvider',
function($stateProvider) {
$stateProvider.
state('/', {
url: '/',
views: {
'': {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
},
'nav#': {
templateUrl: 'path/to/nav.html',
controller: 'NavCtrl'
},
}
}).
state('/inventory/', {
url: '/',
views: {
'': {
templateUrl: 'templates/dash.html',
controller: 'DashCtrl'
},
'nav#': {
templateUrl: 'path/to/nav.html',
controller: 'NavCtrl'
},
}
}).
// ...
and in your index.html
<div ui-view="nav"></div>
<div ui-view ></div>
Take a closer look at UI Router's doc, there's much more you can do with it!

Angular - Navigating to named state from Interceptor

This my main module definition:
$rootScope.$on('unauthorized', function () {
$state.go('login');
});
.config(
function ($stateProvider, $logProvider, $httpProvider) {
$logProvider.debugEnabled(true);
// main application area //
$stateProvider
.state('body', {
url: '/',
template: '<div ui-view />'
});
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'login.html',
controller: 'LoginController',
});
$httpProvider.interceptors.push('APIInterceptor');
});
Interceptor definition:
service('APIInterceptor', function($rootScope) {
// Just for testing
$rootScope.$broadcast('unauthorized');
}
It's not following this:
$state.go('login'); and seems like it's looping until Chrome fails the page. Without $state.go('login'); code runs ok but I need to open the login page on unauthorized. My question is how do I navigate to login state?
Thanks
Try this
$rootScope.$on('unauthorized', function ($state) {
$state.go('login');
});

Angular - same Url "/" but with different templates based on user's logged in status

I am trying to have two different templates. One that is the landing page for logged out users describing about the business and the other dashboard page for if a user is logged in.
I read on this other stack on how to do this with UI-router. I would like to know the best practice to do something similar like this using ngRoute?
The way it is setup below, is that "/frontdesk" is the dashboard and "/" is the landing page for logged out users. BUT! I want the URL to be the same for whether the user is on the dashboard or is logged out and sent to the landing page! I do not want "/frontdesk", I want "/" for IndexController and FrontdeskController.
Here is my routing JS.
(function () {
'use strict';
angular
.module('resonanceinn.routes')
.config(config);
config.$inject = ['$routeProvider'];
function config($routeProvider) {
$routeProvider
.when('/', { // This is the landing Page
controller: 'IndexController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/layout/index.html'
})
.when('/frontdesk', { //This is logged in user that I want to become '/' as well
controller: 'FrontdeskController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/frontdesk/frontdesk.html'
})
.when('/register', {
controller: 'RegisterController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/authentication/register.html'
})
.when('/login', {
controller: 'LoginController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/authentication/login.html '
})
.when('/:username', {
controller: 'ProfileController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/profiles/profile.html'
})
.when('/:username/settings', {
controller: 'ProfileSettingsController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/profiles/settings.html'
}).otherwise('/');
}
})();
Solution!
Thank you everyone for your answers.
Thanks to #ThibaudL for the better solution.
This is how I ended up doing it:
In Routes.js
.when('/', {
controller: 'MainController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/layout/Main.html'
Main.html
<div ng-include="" src="'/static/javascripts/layout/index.html'" ng-if="auth"></div>
<div ng-include="" src="'/static/javascripts/frontdesk/frontdesk.html'" ng-if="!auth"></div>
MainController.js
(function () {
'use strict';
angular
.module('resonanceinn.layout.controllers')
.controller('StartController', StartController);
StartController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];
function StartController($scope, $route, $routeParams, $location, Authentication) {
$scope.auth = Authentication.isAuthenticated();
}
})();
So now if the user is Authenticated, it just switches the templates to the users dashboard.
I added a new div with ng-controller to each template so that each template has their separate controllers.
Add another property, like this isGuest: true
.when('/', {
controller: 'IndexController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/layout/index.html',
isGuest: true
})
.... ...............
and
app.run(function($rootScope, $state, Session) {
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
if (toState.isGuest == true && Session.isAuthenticated()) {
// User isn’t authenticated
// do redirection to guest user
event.preventDefault();
}
if (toState.authentication == true && !Session.isAuthenticated()) {
// do redirection to loggedin user
event.preventDefault();
}
});
});
You can write your own service Session,
Session.isAuthenticated() // returns true or false,based on whether user is guest or loggedin
You can use resolve property to check if user is logged in.
$routeProvider
.when('/somepage' ,{
templateUrl: "templates/template.html",
resolve:{
"check":function($location){
if('Your Condition'){
//Do something
}else{
$location.path('/'); //redirect user to home.
alert("You don't have access here");
}
}
}
})
Inject $locationProvider with your $routeProvider
config.$inject = ['$locationProvider'];
then
function config($routeProvider, $locationProvider ) {
$routeProvider
.when('/', {
controller: 'IndexController',
controllerAs: 'vm',
template: " "
})
...
note its template not templateUrl, also the template is " " note just ""
then in your index controller
.controller('IndexController', function($scope, $route, $routeParams, $location) {
if ($scope.user.loggedIn) $location.path('/:user'); else $location.path('/:visitor');})
note that same path as '/' but /:user for loggedIn users and /:visitor for anonymous
What I would do is :
Main.html
<div ng-include="" src="'/static/javascripts/layout/index.html'" ng-if="auth"></div>
MainController.js
(function () {
'use strict';
angular
.module('App.layout.controllers')
.controller('MainController', MainController);
MainController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];
function MainController($scope, $route, $routeParams, $location, Authentication) {
$scope.auth = Authentication;
});
}
})();
there are a couple of things you can do, the simplest being, checking for a logged in status in the beginning of your FrontdeskController and navigate to the homepage if not logged in.
you can also add variables on the route and check for them like in the previous answer.
there are more extreme cases you can do, which I find to be very bad practice, like writing a double state template page, but again, that's not a good thing to do.
I hope this helped
For templateUrl, you can use a function like,
templateUrl : function(parameter) {
if(loggedin) {
return '/static/javascripts/layout/index.html';
} else {
return 'logged out page';
}
}
You can read $routeProvider,
templateUrl – {string=|function()=} – path or function that returns a path to an html template that should be used by ngView.
If templateUrl is a function, it will be called with the following parameters:
{Array.< Object >} - route parameters extracted from the current $location.path() by applying the current route
Here's a complete solution:
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'IndexController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/layout/index.html'
})
.when('/frontdesk', {
controller: 'FrontdeskController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/frontdesk/frontdesk.html',
requireLogin: true
});
});
app.factory('authService', function () {
var service = {
isAuthenticated: false,
loginPageUrl: '/login'
};
return service;
});
app.run(function ($rootScope, $location, authService) {
$rootScope.$on('$routeChangeStart', function (event, next) {
if (angular.isDefined(next) && next !== null && angular.isDefined(next.requireLogin)) {
if (next.requireLogin === true && !authService.isAuthenticated) {
event.preventDefault();
$location.path(authService.loginPageUrl);
}
}
});
});
First Attempt
.
In Routes.js
.when('/', {
controller: 'MainController',
controllerAs: 'vm',
templateUrl: '/static/javascripts/layout/Main.html'
Main.html
<div ng-include="mainTemplate"></div>
MainController.js
(function () {
'use strict';
angular
.module('App.layout.controllers')
.controller('MainController', MainController);
MainController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];
function MainController($scope, $route, $routeParams, $location, Authentication) {
$scope.$watch(function($scope) {
return $scope.mainTemplate = Authentication.isAuthenticated() ? '/static/javascripts/layout/index.html' : '/static/javascripts/frontdesk/frontdesk.html';
});
}
})();
So now if the user is Authenticated, it just switches the templates to the users dashboard.
I added a new div with ng-controller to each template so that each template has their separate controllers.

Angular not responding to any routes with ui-router - URL just disappears when I enter

I'm using NodeJS+Express to serve an HTML page with an Angular app. It seems to work fine when it loads. There are no errors.
Problem is that that page is pretty much blank - except for the header. But the part that is supposed to go where <div ui-view></div> is, doesn't display anything.
Worse yet, when I go to an address, like
http://localhost:7070/admin/#/rounds
the browser just changes it to
http://localhost:7070/admin/#/
and goes back to displaying nothing.
My angular app, in index.js looks like this:
Some .run() and .config() settings
app.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
// It's very handy to add references to $state and $stateParams to the $rootScope
// so that you can access them from any scope within your applications.For example,
// <li ng-class="{ active: $state.includes('contacts.list') }"> will set the <li>
// to active whenever 'contacts.list' or one of its decendents is active.
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]);
app.config(["$locationProvider", function($locationProvider) {
//$locationProvider.html5Mode(true);
}]);
States definition:
app.config(
['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
console.log("Is this running at all?");
$urlRouterProvider.otherwise('/');
$stateProvider
.state("admin", {
abstract: true,
url: '/admin',
template: '<ui-view />'
})
.state("admin.login", {
url: '/login',
templateUrl: 'login.html',
controller: 'userLoginCtrl'
})
/* DASHBOARD */
.state("admin.dashboard", {
url: "",
controller: 'dashboardAppCtrl',
templateUrl: "dashboard.html"
})
.state("admin.subjects", {
url: "/subjects",
controller: 'subjectsCtrl',
templateUrl: "subjects.html"
})
/* ROUNDS */
.state("admin.rounds", {
url: "/rounds",
controller: 'roundsAppCtrl',
templateUrl: "rounds.html",
resolve: {
gameId: ['$stateParams', function($stateParams){
console.log("gameId ");
return $stateParams.gameId;
}]
}
})
.state("admin.round", {
url: "/round/:roundId",
controller: 'adminRoundCtrl',
templateUrl: "adminround.html",
resolve:{
gameId: ['$stateParams', function($stateParams){
return $stateParams.gameId;
}],
roundId: ['$stateParams', function($stateParams){
return $stateParams.roundId;
}]
},
});
}
]);
There is a working plunker
The answer is relatively simple
$urlRouterProvider.otherwise('/admin');
And instead of this
http://localhost:7070/admin/#/rounds
we have to try this
http://localhost:7070/admin/#/admin/rounds
The point is, every sub-state 'admin.xxx' is child state of the the 'admin' state. And that means, it inherits its url: '/admin'
Also, we used
//$locationProvider.html5Mode(true);
So, the startingurl would most likely be ...
EXTEND: as discussed in comments, IIS Express is used with virtual applicaton /admin, so this part will be in url twice /admin/#/admin...
http://localhost:7070/admin/index.html
// i.e.
http://localhost:7070/admin/
As a starting url of our app. Any routing is later managed after the # sign
http://localhost:7070/admin/#/admin/round/22
Check it here

Resources