AngularJS show login/logout button conditionally in navbar on app page - javascript

Main.jsp
<html>
<body ng-app="myApp">
<div class="navbar">
View Orders
<a href="/logout" ng-show="$scope.isUserLoggedIn"> Logout </label>
<a href="/login" ng-show="!$scope.isUserLoggedIn"> Login </label>
</div>
<div ng-view></div>
</body>
</html>
Controllers
var myApp = angular.module('myApp', ['ngRoute']);
...
// route for the default home page
.when('/', {
templateUrl : function($node, tattrs) {
return "resources/html/home.html";
},
controller : 'mainController'
})
// route for the order page
.when('/order', {
templateUrl : function($node, tattrs) {
return "resources/html/order.html";
},
controller : 'orderController'
})
....
myApp.controller('mainController', function($scope, $http) {
....
$scope.isUserLoggedIn = true; //or false
.....
Question:
The $scope.isUserLoggedIn is having no effect on Login/Logout hrefs. The scope is probably not accessible on the main app page (i.e in the navbar in the ng-app page).
I want to show hide the Login/Logout button conditionally. Any ideas?

You are missing assigning controller to div
No need to use $scope there, just use
<div class="navbar" ng-controller="mainController">
View Orders
<a href="/logout" ng-show="isUserLoggedIn"> Logout </label>
<a href="/login" ng-show="!isUserLoggedIn"> Login </label>
</div>

Related

move from login page to main page in ionic using angular

my code is working fine. but when i click on login button it changes the state as shown in the pic, it is changing its url but not opening that page.any help how can i redirect to next page?
index.html
<body ng-app="starter">
<ion-nav-view></ion-nav-view>
</body>
login.html
<ion-view view-title="login">
<ion-header-bar>
<h1 class="title">Login</h1>
<div class="buttons">
<button class="button button-clear" ng-click="closeLogin()">Close</button>
</div>
</ion-header-bar>
<ion-content>
<form ng-submit="doLogin()">
<div class="list">
<label class="item item-input">
<span class="input-label">Username</span>
<input type="text" ng-model="loginData.username">
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" ng-model="loginData.password">
</label>
<label class="item">
<button class="button button-block button-positive" type="submit">Log in</button>
</label>
</div>
</form>
</ion-content>
</ion-view>
app.js
angular.module('starter', ['ionic', 'starter.controllers'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/app',
templateUrl: 'templates/login.html',
controller: 'AppCtrl'
})
.state('app.menu', {
url: '/home',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.search', {
url: '/search',
views: {
' menuContent': {
templateUrl: 'templates/search.html'
}
}
})
});
Controllers.js
angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope, $ionicModal, $timeout, $state) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//$scope.$on('$ionicView.enter', function(e) {
//});
// Form data for the login modal
$scope.loginData = {};
// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope
}).then(function(modal) {
$scope.modal = modal;
});
// Triggered in the login modal to close it
$scope.closeLogin = function() {
$scope.modal.hide();
};
// Open the login modal
$scope.login = function() {
$scope.modal.show();
};
// Perform the login action when the user submits the login form
$scope.doLogin = function() {
console.log('Doing login', $scope.loginData);
$state.go('app.search');
// Simulate a login delay. Remove this and replace with your login
// code if using a login system
$timeout(function() {
$scope.closeLogin();
}, 1000);
};
})
You made the search state being a child state of the app state (which displays your login).
So it will first display the template with the login, and this template does not include anything to help the other state being shown.
I think you want your states to be :
login with url /login
app with url /app and abstract
And then app.search with url /search.
Then in your url bar you will see /app/search and it will be the right URL and right state you are looking for.

Web Page not Anchoring in Angular

I am attempting to have the page go to a div section of the page based on what they click. I have the div for each section id'd with the proper tag. I have done a test where I can load the page and type url.com/services#insertidhere and it will go to the correct location. The issue is when I try to implement it in the state it won't go to the location. It just goes to the page normally even though the URL shown is correct.
HTML Index Snippet
<div ng-repeat="x in blue.services">
<div class="wrapIMG">
<img src="{{x.icon}}" />
<img class="clone" src="{{x.icon}}" />
</div>
<h4>{{x.title}}</h4>
<hr/>
<p>{{x.text}}</p>
<a ui-sref="services({id: x.title})" class="button2">About This</a>
</div>
myapp.js Snippet
app.config(function($stateProvider){
$stateProvider
.state('index', {
url:"/",
templateUrl: 'main.html',
data: {
cssId: 'home'
}
})
.state('services', {
url: "/services/#:id",
templateUrl: 'services.html',
data: {
cssId: 'services'
}
})
});
Services HTML Snippet
<section class="no-padding" style="" id="[id equal to x.title]"> ...</section>
<section class="no-padding" style="" id="[id equal to x.title]"> ...</section>
<section class="no-padding" style="" id="[id equal to x.title]"> ...</section>
I believe the issue has to be with .state URL but it shows correctly in the URL but it just isn't going to the location.
Angular uses the # in URLs for page routing (so do many other SPA frameworks).
To anchor the link to a specific id on a page, use the $anchorScroll service.
Example:
<div id="scrollArea" ng-controller="ScrollController">
<a ng-click="gotoBottom()">Go to bottom</a>
<a id="bottom"></a> You're at the bottom!
</div>
<script>
angular.module('anchorScrollExample', [])
.controller('ScrollController', ['$scope', '$location', '$anchorScroll',
function($scope, $location, $anchorScroll) {
$scope.gotoBottom = function() {
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');
// call $anchorScroll()
$anchorScroll();
};
}]);
</script>
$scope.toPage = function(){$state.go('index');}
Did you try this?

Angular Routing - Load data into parent page before first route

I am using angular routing for a admin panel project. Following is my angular js code.
app.js
(function() {
var app = angular.module("app", [
"ngRoute",
"app.dashboard",
"app.calendar",
"app.event"
]);
var dashboard = angular.module("app.dashboard");
dashboard
.config(function($routeProvider) {
$routeProvider.
when('/dashboard', {
templateUrl: '/views/dashboard/dashboard.html',
controller: 'DashBoardIndexController as ctrl'
}).
when('/dashboard/detail', {
templateUrl: "/views/dashboard/detailgraph.html",
controller: "DashBoardDetailController as ctrl"
})
});
......
......
//Controllers related to dashboard module
var calendar = angular.module("app.calendar");
calendar
.config(function($routeProvider) {
$routeProvider.
when('/calendar', {
templateUrl: '/views/calendar/calendar.html',
controller: 'CalendarIndexController as ctrl'
}).
when('/calendar/markevent', {
templateUrl: "/views/calendar/markevent.html",
controller: "CalendarEventController as ctrl"
})
});
......
......
//Controllers related to calendar module
}());
For better code management, I am dividing various module of application and including them in main app module.
After login, the first route loaded will be of dashboard (/dashboard). But before route provider initialized and dashboard loaded, I need to fetch the user's rights level and accordingly create the side navigation menus in parent page. Below is my parent page:
home.html
<body ng-app="app">
<header>
<nav id="mynav" class="bold z-depth-1" role="navigation">
<div class="nav-wrapper container">
<a id="logo-container" href="#" class="brand-logo text-darken-1">Logo</a>
<div class="container">
<a href="#" data-activates="slide-out" class="button-collapse top-nav full hide-on-large-only black-text"><i
class="mdi-navigation-menu"></i></a>
</div>
</div>
</nav>
<ul id="slide-out" class="side-nav fixed center-align">
<!-- This side menu items should be created based on user's rights --!>
</ul>
</header>
<main class="grey lighten-4">
<div id="main-container" class="container z-depth-1 ">
<div ng-view=""></div>
</div>
</main>
As you can see, before ng-view is loaded with first route (/dashboard), I need to make server call to fetch the user's rights. I am relatively new to angular and I think we can do this by resolve promise. But here two modules are different (app and app.dashboard).
What could be the correct way to solve this problem?

ngHide directive only works with ngRoute module after page refresh

When I login on my app, I want the login and signup button to disappear from the nav so I am using ng-hide directive if the login was successful and a token was received from the server, which I store in the cookies.
Nav is part of the index.html file.
Because I am using angular routing, when login is successful, index.html is not loaded again instead I render the home page through ng-view directive.
The problem is I have to refresh the page for ng-hide to work. I am assuming it is because ng-hide is part of index.html page, which does not get reloaded.
Hoping there is a bette solution than refreshing the page every time someone logs in.
Here is some of my relevant code.
HTML
<!-- Navigation -->
<nav class="navbar navbar-custom navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse">
<i class="fa fa-bars"></i>
</button>
<a class="navbar-brand page-scroll" href="#/">
<i class="fa fa-play-circle"></i> <span class="light">Webnar</span>
</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-right navbar-main-collapse">
<ul class="nav navbar-nav">
<!-- Hidden li included to remove active class from about link when scrolled up past about section -->
<li class="hidden">
</li>
<li>
<a class="page-scroll" href="#about">Webinars</a>
</li>
<li ng-hide="token">
<a class="page-scroll" href="#/login">Login</a>
</li>
<li ng-show="token">
<a class="page-scroll " href="#/create">Add a webinar</a>
</li>
<li ng-hide="token">
<a class="page-scroll btn btn-default " href="#/signup">Sign Up</a>
</li>
<li ng-show="token" >
<a class="page-scroll btn btn-default" ng-click="logOut()">Logout</a>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
App.js
var webinarApp = angular.module('webinarApp', ['ngCookies', 'ngRoute']);
webinarApp.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: './home.html',
controller: 'mainController'
})
.when('/signup', {
templateUrl: './signup.html',
controller: 'mainController'
})
.when('/login', {
templateUrl: './login.html',
controller: 'mainController'
})
.when('/create', {
templateUrl: './create.html',
controller: 'mainController'
})
});
webinarApp.controller('mainController', ['$scope', '$http', '$cookies', '$location', function($scope, $http, $cookies, $location){
$scope.welcomeMessage = '';
$scope.users = [];
$scope.searchQuery = "";
$scope.orderByField = 'name';
$scope.newUser = {};
$scope.logInUser = {};
$scope.webinars = [];
$scope.newWebinar = {};
$scope.isDisabled = false;
// ============== Users ================
$scope.getUsers = function(){
$http.get('/api/users').then(function(response){
$scope.users = response.data;
});
};
$scope.getUsers();
$scope.createUser = function(){
$http.post('/api/users', $scope.newUser).then(function(response){
console.log(response.data)
$scope.users.push(response.data);
$scope.newUser = {};
$location.path('/login');
});
};
$scope.obtainToken = function(){
$http.post("/api/users/authentication_token", $scope.logInUser).then(function(reponse){
$scope.token = reponse.data.token;
console.log($scope.token);
$cookies.put('token', $scope.token);
$location.path('/')
});
};
It's because you put the navbar on the index page. It's not a template that is loaded by the route module. So it's not related to any route and controller that are bind with it. Controller declared in routes only applies for template that are loaded by the route module.
To bind a controller whatever the route is use ng-controller directive. Put it on your <nav> element
Note if you use the "as controller" syntax you must do in controller :
this.isDisabled
instead of
$scope.isDisabled
Documentation : https://docs.angularjs.org/#!/api/ng/directive/ngController
If you need to update datas to that controller with the rest of the application. Use $rootScope. If you use 'ctrl as' syntax, the easier is to do :
this.$rootScope=$rootScope;
If you don't like this use $watch to watch for changes and rebind the currentValue to the controller :
$rootScope.watch('myParameter', function(new){
this.myParameter = new;
});
AND DON'T FORGET TO INITIALIZE THE VARIABLE IN $ROOTSCOPE. Or the variable will end up in a child scope that won't be visible for your navbar's controller.
You should declare $scope.token with your other variable declarations. It does not exist in the scope when you are initially setting your ng-hide.
$scope.isDisabled = false;
$scope.token;
Have you tried using $scope.$apply() ???
$scope.$apply(function() {
$scope.token = <whatever value>;
})
Ok i think one way to do this would be to add a controller for nav say navbarController.
<nav ng-controller="navbarController">...</nav>
Inject $rootScope into both maincontroller and navbarController.
then in mainController whenever you need to change value of token, do this
$rootScope.$emit('tokenValueChange', <value>);
then in navbarController add,
$rootScope.$on('tokenValueChange', function(newValue) {
$scope.token = newValue;
})
I am not sure if this is a perfect method but this should work.
I had a similar problem as OP (viditsaxena), and solved it the same way he did. Like him, I had ng-hide in my nav which was located in index.html. My ng-hides worked correctly on initial page load, but when I tried to navigate to a different view, my ng-hide's would not work until I refreshed the page.
My solution: The same way #viditsaxena describes in his comments under the accepted answer (use $rootScope instead of $scope), but I thought I'd put my actual code here to show you how I made it work in my app.js file:
I went from this (ng-hide required refresh to load after I navigated away from the original view):
app.controller('routeController', ['$scope', '$location', function($scope, $location) {
$scope.showPortfolioHeader = $location.path() === '/jcRealty';
}]);
To this (now my ng-hides don't require a refresh after I navigate away from my first view):
app.controller('routeController', ['$rootScope', '$location', function($rootScope, $location) {
$rootScope.showPortfolioHeader = $location.path() === '/jcRealty';
}]);
The accepted answer got me part of the way there, but I had a hard time deciphering some of the grammar in his response. My own testing confirmed some of what he said. My controller above (routeController) is related to the view located at the /jcRealty path. If I put my ng-hides in my jcRealty view, they work properly (no refresh needed) using $scope. But since my ng-hide's are on index.html, outside of that controller's path, $rootScope was needed to not require a page reload.

ngClass not updating the class

I am using angularJS with bootstrap to design a navigation on my application. I have defined a main controller and inside the main controller I call different page views using the ng-view attribute and then these individual views have their own controllers.
I am using the ng-class attribute to add the active class to my links, however, it is not working. The expression evaluates to true or false but the ng-class does not updates the class="active" on the elements.
On my home page I have the following code -
<section ng-controller="dashBoardCtrl" class="container">
<section class="row">
<h1>DME DashBoard | <small>WFM HeadCount</small> </h1>
</section>
<section class="row">
<ul class="nav nav-tabs">
<li role="presentation" ng-class="{active: {{path=='/'}}}"><a ng-href="#/">Home</a></li>
<li role="presentation" ng-class="{active: {{path=='/login'}}}"><a ng-href="#/login">Login</a></li>
</ul>
</section>
<section ng-view></section>
</section>
This is how the routes are configured on the app -
dmeDash.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/views/home.html',
controller: 'homePageCtrl'
})
.when('/login', {
templateUrl: '/views/login.html',
controller: 'loginCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
The dashBoardCtrl have the following code -
dmeDashControllers.controller('dashBoardCtrl', ['$scope','$location', function($scope, $location) {
$scope.path = $location.$$path;
$scope.$watch('path',function(n,o) {
})
}]);
Home Page Controller has the following code -
dmeDashControllers.controller('homePageCtrl', ['$scope','$location', function($scope, $location) {
$scope.$parent.path = $location.$$path;
}]);
The log in page controller has the following code -
dmeDashControllers.controller('loginCtrl', ['$scope','$location', function($scope, $location) {
$scope.$parent.path = $location.$$path;
}]);
When I click from Home page to Login page the active class is not removed from home page link and not applied to the login page as well, however, when I view the code in firebug the expressions evaluates to true or false when the page changes.
When I refresh on individual pages the ng-class works correctly but not when using the hyperlinks, please suggest.
The syntax is wrong on the template. It should be:
<li role="presentation" ng-class="{'active': path==='/'}"><a ng-href="#/">Home</a></li>
And as style guide try using the === instead of the simple == because of type coercion. Or test agains truthy or falsy

Categories

Resources