I'm managing authentication with JWT. I'm trying to use ng-hide and ng-show to show/hide login and logout buttons in my nav. It's not working. The token is being stored, but I'm unable to get the show/hide to work.
Service:
angular.module('psJwtApp')
.factory('authToken', function ($window) {
var storage = $window.localStorage;
var cachedToken;
var userToken = 'userToken';
var isAuthenticated = false;
var authToken = {
setToken: function (token) {
cachedToken = token;
storage.setItem(userToken, token);
isAuthenticated = true;
},
getToken: function () {
if(!cachedToken)
cachedToken = storage.getItem(userToken);
return cachedToken;
},
isAuthenticated: function () {
return !!authToken.getToken();
},
removeToken: function () {
cachedToken = null;
storage.removeItem(userToken);
isAuthenticated = false;
}
};
return authToken;
});
Controller:
angular.module('psJwtApp')
.controller('HeaderCtrl', function ($scope, authToken) {
$scope.isAuthenticated = authToken.isAuthenticated();
});
html:
<div ng-controller="HeaderCtrl" class="header">
<ul class="nav nav-pills pull-right">
<li ui-sref-active="active">
<a ui-sref="main">Home</a>
</li>
<li ui-sref-active="active">
<a ui-sref="jobs">Jobs</a>
</li>
<li ng-hide="isAuthenticated()" ui-sref-active="active">
<a ui-sref="login">Log In</a>
</li>
<li ng-show="isAuthenticated()" ui-sref-active="active">
<a ui-sref="logout">Logout</a>
</li>
</ul>
<h3 class="text-muted">psJwt</h3>
</div>
Have you checked the type of $scope.isAuthenticated? i suspect that it has resolved to a boolean, not a function. Update your html to check against the boolean value.
<li ng-show="!isAuthenticated" ui-sref-active="active">
<a ui-sref="login">Log In</a>
</li>
<li ng-show="isAuthenticated" ui-sref-active="active">
<a ui-sref="logout">Logout</a>
</li>
Related
When we click on Menu item list, it routes to login page:
How can i solve this problem?
This my sidemenu-template:
<ul class="page-sidebar-menu page-header-fixed page-sidebar-menu-hover-
submenu " data-keep-expanded="false" data-auto-scroll="true" data-
[enter image description here][1]slide-speed="200">
<li class="nav-item" data-ng-repeat="menu in sideBarCntrl.menuList">
<a href="#/{{menu.menuUrl}}" class="nav-link nav-toggle">
<i class="{{menu.menuIcon}}"></i>
<span class="title"> {{menu.menuDisplayName}}</span>
<span class="arrow"></span>
</a>
<ul class="sub-menu">
<li class="nav-item" data-ng-repeat="childmenu in menu.childMenuItems">
<a href="#{{childmenu.menuUrl}}" class="nav-link ">
<span class="title">{{childmenu.menuDisplayName}}</span>
</a>
</li>
</ul>
</li>
</ul>
This is my sidemenu- main list directive calling Api Using ASP.Net:
sideBarCntrl.getMenuList = function() {
user.allowWeb = true;
dashboardService.getMenuList(user).then(function(response) {
//console.log(response.data);
sideBarCntrl.menuList = response.data;
angular.forEach(sideBarCntrl.menuList, function(value, key) {
if ($state.current.url == ('/' + value.menuUrl)) {
value.isActive = true;
}
})
}, function(error) {
if (error.data.message) {
toastr.error(error.data.message);
}
});
}
I would recommend using ng-href instead of href in your case. This way you are sure the link is not broken even if the user clicks the link before AngularJS has evaluated the code.
I know I am suppose to do and ng-hide="something", but I don't where to go from there. Not sure if I have to also write another function in my logoutController or mainController.
<ul class="right hide-on-med-and-down">
<li><a ui-sref="login">Login</a></li>
<li><a ui-sref="logout" ng-click='logoutCtrl.logout()'>Logout</a></li>
</ul>
</div>
nav.html
function logoutController($state, AuthService) {
var vm = this
vm.logout = function () {
// call logout from service
AuthService.logout()
.then(function () {
$state.go('login')
})
}
}
app.js
It depend the way you're login works but you can do
<ul class="right hide-on-med-and-down">
<li><a ng-show="inNotLogged"ui-sref="login">Login</a></li>
<li><a ui-sref="logout" ng-click='logoutCtrl.logout()'>Logout</a></li>
</ul>
</div>
and in your app.js .run set $rootScope.isNotLogged = true;then in your login method:
$rootScope.isNotLogged = false;
$scope.isNotLogged = $rootScope.isNotLogged;
so in tour lgout you will set
$scope.isNotLogged = true;
$rootScope.isNotLogged = $scope.isNotLogged;
I have the following layout:
<nav ng-include="'views/nav.html'"></nav>
<div class="container-fluid">
<div ng-view></div>
</div>
Inside nav.html I want to display a dropdown link, once someone has entered a page, and has access. This page is rendered in the ng-view div
Right now I am using a service to update the shared value from one controller to the nav controller. However, the value is never updated in the nav controller. It is set in the service, but not updated.
<nav class="navbar navbar-inverse" role="navigation" ng-controller="LoginController as login">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li>Show option '{{login.showOption}}' <span class="glyphicon glyphicon-info-sign"></span></li>
<li ng-if="login.showOption" dropdown>
<a href class="dropdown-toggle" dropdown-toggle>
Options <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a ng-href>1</a></li>
<li><a ng-href>2</a></li>
</ul>
</li>
</ul>
</div>
</nav>
LoginController.js
var LoginController = function (Option) {
var model = this;
model.showOption = Option.getValue();
module.controller("LoginController", ['Option', LoginController]);
}(angular.module("myApp")));
Option.js
'use strict';
(function (module) {
var option = function () {
var value = false;
return {
getValue: function() {
return value;
},
setValue: function(newVal) {
value = newVal;
}
};
};
module.service("Option", option);
}(angular.module("civApp")));
I am updating the Option.getValue() from another controller in another view, however the nav isn't getting updated.
GameController.js
var GameController = function (Option) {
Option.setValue(true);
module.controller("GameController", ['Option', GameController]);
}(angular.module("myApp")));
When I call this code, the view in the nav.html is not updated. I can see that the Option service is called, but I was hoping the value would have been updated in the view also.
GameController
LoginController
Nav.html
I can clearly see in GameController#watch that the Option.value:show is correctly set to true
That can be sorted using by angular dot rule
just update your code to :
Option Service
(function (module) {
var option = function () {
//value.show instead value
var value = {
show: false
};
return {
value: value
};
};
module.service("Option", option);
}(angular.module("civApp")));
and after that in your controllers
Login
var LoginController = function (Option) {
var model = this;
model.showOption = Option.value;
module.controller("LoginController", ['Option', LoginController]);
}(angular.module("myApp")));
GameController
var GameController = function (Option) {
Option.value = {
show: true
};
module.controller("GameController", ['Option', GameController]);
}(angular.module("myApp")));
and finally in your view
<li>Show option '{{login.showOption.show}}' <span class="glyphicon glyphicon-info-sign"></span>
I wanna see a div when I put the mouse over an image and remove it if I leave the mouse, with the ng-mouseenter and ng-mouseleave. But when I load my page, in the div appear class="ng-hide".
My code:
<nav class="navbar-default navbar-side" role="navigation" ng-app="panel" ng-controller="panelController">
<div class="sidebar-collapse">
<ul class="nav" id="main-menu">
<li class="text-center">
<img ng-mouseenter="inProfile()" ng-mouseleave="outProfile()" src="{{ asset('image/id1.jpg') }}" class="user-image img-responsive"/>
<div ng-show="panelController.evento">
Hi!!
</div>
</li>
<li>
<i class="fa fa-dashboard fa-3x"></i><span class="text-20">Dashboard</span></a>
</li>
<li>
<i class="fa fa-users fa-3x"></i><span class="text-20">Usuarios</span>
</li>
<li>
<i class="fa fa-lightbulb-o fa-3x padding-left-10"></i><span class="text-20 padding-left-10">Emprendedores</span></a>
</li>
<li>
<i class="fa fa-money fa-3x"></i><span class="text-20">Inversores</span></a>
</li>
<li>
<i class="fa fa-newspaper-o fa-3x"></i><span class="text-20">Noticias</span></a>
</li>
</ul>
</div>
</nav>
<script>
var tfc = angular.module('panel', []);
tfc.controller ( 'panelController' , [ '$scope' , function($scope){
$scope.inProfile = function(){
$scope.evento = "true";
}
$scope.outProfile = function(){
$scope.evento = "false";
}
}])
</script>
You problem is on page load eventto value is undefined that's why ng-show expression is hiding value on page load. you should define evento value to true to show it. You could this do from controller or also you could use ng-init="panelController.evento=true" on view
And make sure, you should use boolean rather than string which is used for expression evaluation in ng-show.
Code
var tfc = angular.module('panel', []);
tfc.controller('panelController', ['$scope', function($scope) {
$scope.inProfile = function() {
$scope.evento = true;
}
$scope.outProfile = function() {
$scope.evento = false;
}
//init values
$scope.evento = true;
}]);
Update
You should directly access value of scope variable on view as you are not using controllerAs in you application, it should be evento instead of panelController.evento
Markup
<div ng-show="evento">
Hi!!
</div>
My problem is similar to this : ng-show and ng-hide with jwt
Although i modified as instructed by user3735441, i still can't make them work properly:
Service :
'use strict';
/**
* #ngdoc service
* #name ToDoManagerApp.authToken
* #description
* # authToken
* Factory in the ToDoManagerApp.
*/
angular.module('ToDoManagerApp').factory('authToken', function($window) {
var storage = $window.localStorage;
var cachedToken;
var userToken = 'userToken';
var isAuthenticated = false;
// Public API here
var authToken = {
setToken: function(token) {
cachedToken = token;
storage.setItem(userToken, token);
isAuthenticated = true;
},
getToken: function() {
if(!cachedToken)
cachedToken = storage.getItem(userToken);
return cachedToken;
},
isAuthenticated: function() {
return !!authToken.getToken();
},
removeToken: function() {
cachedToken = null;
storage.removeItem(userToken);
isAuthenticated = false;
}
};
return authToken;
});
Controller :
angular.module('ToDoManagerApp').controller('HeaderCtrl', function($scope, authToken) {
$scope.isAuthenticated = authToken.isAuthenticated;
});
HTML :
<div ng-controller = "HeaderCtrl" class="header">
<div class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#js-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/">ToDoManager</a>
</div>
<div class="collapse navbar-collapse" id="js-navbar-collapse">
<ul class="nav navbar-nav">
<li ui-sref-active="active">
<a ui-sref="main">Home</a>
</li>
<li ng-hide="isAuthenticated()" ui-sref-active="active">
<a ui-sref="register">Register</a>
</li>
<li ng-show="isAuthenticated()" ui-sref-active="active">
<a ui-sref="logout">Logout</a>
</li>
</ul>
</div>
</div>
</div>
</div>
What i'm trying to do is to :
1 - show register, hide logout when no token is set (not authenticated) OR
2 - show logout, hide register when a token is set (authenticated)
For now i'm stuck with the first state, authenticated or not i can't see the logout button.
You are accessing the $scope model with ng-hide and ng-show.
In your Service, you are setting isAuthenticated to false, and never setting it to True. So your app is stuck in your first state, where the isAuthenticated is false.
I completly forgot to add 'res' in my register controller, that's why it wasn't updated :
$http.post(url, user)
.success(function(res) {
alert('success', 'OK!', 'You are now registered');
authToken.setToken(res.token);
})
This is happening because your variable in your controller is not updating when it changes in your factory. To work around this, I usually use $broadcast. So in your factory you would have some function like this...
var broadcastValue = function() {
$rootScope.$broadcast('IsAuthenticated');
}
You would then call this function at whatever point you wanted the receivers to check the variable.
Then in your controller you would have something like this to receive the broadcast
$scope.$on('IsAuthenticated', function() {
$scope.isAuthenticated = authToken.isAuthenticated;
});
This will make sure your controller sees when the value changes.
Also see this post.
$on and $broadcast in angular