So here is my code for my view:
<ul class="nav nav-pills" id="my-pill">
<li class="active"><a href="#tab0" data-toggle="tab">Tools
Home</a></li>
<li>Fair Trade Judge</li>
<li>Awards</li>
<li>Draft Buddy</li>
<li>Add A League</li>
<li>Insult Generator</li>
<li>League Poll</li>
<li>Smart Rankings</li>
<li>Composite Rankings</li>
<li><a href="#tab9" data-toggle="tab">Waiver Wire Pickup
Aid</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab0">
<div class="row">
<div class="col-md-12">
<h2>Tool Descriptions</h2>
<h3>Fair Trade Judge</h3>
<p>This tool will help you decide whether or not a proposed
trade is fair</p>
<h3>Awards</h3>
<p>Weekly awards given out to teams who have the best, and
worst weeks in the league</p>
<h3>Draft Buddy</h3>
<p>Use this tool to aid you during your big draft day</p>
<h3>Add A League</h3>
<p>This isn't really a tool, and doesn't fit on the
dashboard</p>
<h3>Insult Generator</h3>
<p>Let our team analysis algorithm pick apart any team in
your league with relevant insults</p>
<h3>League Poll</h3>
<p>Rank every team in your league on a weekly basis. Overall
rankings will be calculated based on the poll</p>
<h3>Smart Rankings</h3>
<p>This tool ranks every team in your league based on
complex rankings algorithm, that factors in more than just your
W-L-T record</p>
<h3>Composite Rankings</h3>
<p>Ever wonder what your record would be if you played every
team every week instead of the head to head match-up style?
This tool will tell you what your overall record would be</p>
<h3>Waiver Wire Pickup Aid</h3>
<p>See who our analysis of your team determines you should
pick up off of the waiver wire this week</p>
</div>
</div>
</div>
<div class="tab-pane" id="tab1" >
<h2>Select the teams that are going to do a trade, then
select the players</h2>
<div ng-controller="FTJController" class="teamWrapper">
<div class="col-md-6 team" style="float: left;">
{{list1}} <select ng-model="selectedTeam1"
ng-options="item as item.teamName for item in teams track by item.teamID"
ng-change="getRoster1(selectedTeam1)">
<option value="">Team 1</option>
</select>
<table class="table-striped" style="width: 100%">
<tr>
<td></td>
<td>Name</td>
<td>Position</td>
<td>NFLTeamName</td>
<td>InjuryCode</td>
</tr>
<tr ng-repeat="player1 in roster1">
<td><input type="radio" ng-value="{{player1.PlayerID}}"
ng-model="selected1" ng-change="addID1(selected1)"
name="selected1" /></td>
<td>{{player1.Name}}</td>
<td>{{player1.Position}}</td>
<td>{{player1.NFLTeamName}}</td>
<td>{{player1.InjuryCode}}</td>
</tr>
</table>
</div>
<div class="col-md-offset-6 team">
{{list2}} <select ng-model="selectedTeam2"
ng-options="item as item.teamName for item in teams track by item.teamID"
ng-change="getRoster2(selectedTeam2)">
<option value="">Team 2</option>
</select>
<table class="table-striped" style="width: 100%">
<tr>
<td></td>
<td>Name</td>
<td>Position</td>
<td>NFLTeamName</td>
<td>InjuryCode</td>
</tr>
<tr ng-repeat="player2 in roster2">
<td><input type="radio" ng-value="{{player2.PlayerID}}"
ng-model="selected2" ng-change="addID2(selected2)"
name="selected2" /></td>
<td>{{player2.Name}}</td>
<td>{{player2.Position}}</td>
<td>{{player2.NFLTeamName}}</td>
<td>{{player2.InjuryCode}}</td>
</tr>
</table>
</div>
<br />
<div class="button">
<input type="button" value="compare players"
ng-click="comparePlayers()" />
<div>Is this trade fair? {{FTJ}}</div>
</div>
</div>
</div>
Whenever I try to click on one of the tabs, instead of loading the data, it will redirect me to my login page. I don't want any redirection, since all the data I need loaded after login. If I change the class of tab1 to active, I get the data behavior I want, so I think it's an issue with Bootstrap. Any ideas?
EDIT: Here is my controller file (the calls to API are working fine)
HomeController.$inject = ['UserService', '$rootScope'];
function HomeController(UserService, $rootScope) {
var vm = this;
vm.user = null;
vm.allUsers = [];
vm.deleteUser = deleteUser;
initController();
function initController() {
loadCurrentUser();
}
function loadCurrentUser() {
UserService.GetByEmail($rootScope.globals.currentUser.email)
.then(function (user) {
vm.user = user.data;
});
}
function deleteUser(id) {
UserService.Delete(id)
.then(function () {
loadAllUsers();
});
}
}
FTJController.$inject = ['$scope', '$http'];
function FTJController($scope, $http) {
$scope.list1 = 'Select Team 1';
$scope.list2 = 'Select Team 2';
//$scope.selectedTeam = null;
$scope.teams = [];
$scope.players1 = [];
$scope.players2 = [];
$scope.roster1 = null;
$scope.roster2 = null;
$http({
method: 'GET',
url: './rest/LeagueTeams?LeagueID=1682132'
}).success(function (result) {
$scope.teams = result;
});
console.log("in controller");
$scope.getRoster1 = function(selectedTeam){
console.log("in getRoster with teamID = " + selectedTeam.teamID);
$http({
method: 'GET',
url: './rest/Roster?LeagueID=1682132&TeamID=' +selectedTeam.teamID + '&Week=1&Year=2015'
}).then(function (result){
$scope.roster1 = result.data;
});
}
//duplicating for now, should change to use the same method for both rosters
$scope.getRoster2 = function(selectedTeam){
console.log("in getRoster with teamID = " + selectedTeam.teamID);
$http({
method: 'GET',
url: './rest/Roster?LeagueID=1682132&TeamID=' +selectedTeam.teamID + '&Week=1&Year=2015'
}).then(function (result){
$scope.roster2 = result.data;
});
}
$scope.comparePlayers = function(){
console.log("testingsss");
console.log($scope.players1);
console.log($scope.players2);
console.log('call: ./rest/FTJ?PlayerID1=' + $scope.players1 + '&PlayerID2=' + $scope.players1);
console.log('Is $scope.players1 ' + ($scope.players1) + ' > $scope.players2 ' + $scope.players1 + ' ?');
console.log('comparison');
console.log($scope.players1 > $scope.players2);
$http({
method: 'GET',
url: './rest/FTJ?PlayerID1=' + $scope.players1 + '&PlayerID2=' + $scope.players2
}).then(function (result){
console.log('result.data');
console.log(result.data);
if (result.data){
$scope.FTJ = "Hell yea";
} else {
$scope.FTJ = "f no";
}
});
};
$scope.addID1 = function(s){
$scope.players1 = s;
console.log($scope.players1);
};
$scope.addID2 = function(s){
$scope.players2 = s;
console.log($scope.players2);
};
}
And here is my app.js file with the routing:
(function () {
'use strict';
angular
.module('app', ['ngRoute', 'ngCookies'])
.config(config)
.run(run);
config.$inject = ['$routeProvider', '$locationProvider'];
function config($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
controller: 'HomeController',
templateUrl: 'home/home.view.html/',
controllerAs: 'vm'
})
.when('/login', {
controller: 'LoginController',
templateUrl: 'login/login.view.html',
controllerAs: 'vm'
})
.when('/register', {
controller: 'RegisterController',
templateUrl: 'register/register.view.html',
controllerAs: 'vm'
})
.otherwise({ redirectTo: '/login' });
}
run.$inject = ['$rootScope', '$location', '$cookieStore', '$http'];
function run($rootScope, $location, $cookieStore, $http) {
// keep user logged in after page refresh
$rootScope.globals = $cookieStore.get('globals') || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.authdata; // jshint ignore:line
}
$rootScope.$on('$locationChangeStart', function (event, next, current) {
// redirect to login page if not logged in and trying to access a restricted page
var restrictedPage = $.inArray($location.path(), ['/login', '/register']) === -1;
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage && !loggedIn) {
$location.path('/login');
}
});
}
})();
How do I fix the routing so that when I click on tab1, it will just show the data and move to that tab instead of redirecting to login? Thanks!
It happens because of angular routing...
You can just add to every anchor tag the following attribute
target="_self"
For example: <li>Fair Trade Judge</li>
Hope it resolves it.
You can use data-target="#tab1" instead of href="#tab1"
Angular router is routing to #tab1 when you click on the link. Since there is no such route defined and login screen is the default route, it must be displaying the login screen.
you could use angular-ui to get bootstrap work easily with angular.
Your default page because there is no defined route to be found.
So, what you can do is you can handle tab click event and prevent this default behaviour using
e.preventDefault();
you have two options:
add ng-click="show($event)" for each tab
For example, in controller
$scope.show = function (e) {
e.preventDefault();
jQuery('.nav-pills[href="e.targrt.hash"]').tab('show')
};
Check Bootstrap document for more detail: http://getbootstrap.com/javascript/#tabs
or add directive to handle event.
<a show-tab href="#tab0" data-toggle="tab">Tools Home</a>
app.directive('showTab', function () {
// here first prevent deault behaviour of a tab, then add new click event which invokes jQuery related stuff for tabs
return function (scope, iElement, iAttributes) {
iElement.click(function (e) {
e.preventDefault();
$(iElement).tab('show');
});
};
This is the better option.
Please check this link how to do it: https://www.grobmeier.de/bootstrap-tabs-with-angular-js-25112012.html
Try this adding to your angjularjs
$(".yourTabClassName anchorTag").click(function(anyName) {
anyName.preventDefault();
});
Ex:
$(".nav a").click(function(e) {
e.preventDefault();
});
buddy, I think you are missing role='tab' attribute which does not invoke the angular router
I got it working by doing this. You'll notice that i'm using <app-tab-profile></app-tab-profile> in the Profile tab-pane. I'm not sure if this is best practice, but it seems to work. Routing is NOT setup for the TabProfileComponent.
<div class="section-container">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">...</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab"><app-tab-profile></app-tab-profile></div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">...</div>
</div>
Hope this helps!
setTimeout(function() {
$('ul.tabs').tabs();
}, 100);
Related
New to angular. I have a custom directive which basically is a form that I want to call when a click event happens when a track within an album is clicked. Something like this:
- album1
*album1-track1
*album1-track2
- album2
So when I click Album1, I will be displaying tracks for album1. When I click album2, I will display tracks of album2 and not for album1. Now, when I click on track of album 2, I want to display the form (which is defined as a custom directive). Something like this:
- album1
*album1-track1 ---> (this track clicked) -----> (form displayed)
*album1-track2
- album2
Here is my code:
// HTML
<div class="wrapper wrapper-content">
<div>
<ul>
<li ng-repeat="album in vm.albums">
<a ng-click="vm.getAlbumTracks(album, $index)">{{album}}</a>
<ul ng-show="$index === vm.showingAlbumIndex">
<li ng-repeat="track in vm.albums.tracks"><a ng-click="vm.displayForm(track)">{{track}}</a></li>
</ul>
</li>
</ul>
<metadata-form></metadata-form>
<a ng-click="vm.newFunction('RAVI')">Click Me!</a>
</div>
Controller:
(function (){
angular.module('app.fileUploadForm').controller('FileUploadFormController', FileUploadFormController);
FileUploadFormController.$inject = ['$http', '$log', '$scope', '$state', '$rootScope', 'APP_CONFIG'];
function FileUploadFormController ($http, $log, $scope, $state, $rootScope, APP_CONFIG){
var vm = this;
vm.albums = init;
vm.getAlbumTracks = getAlbumTracks;
vm.newFunction = newFunction;
vm.displayForm = displayForm;
return init();
function init(){
$http.get('http://localhost:8080/api/albums').then(function(responseData){
// Parse the json data here and display it in the UI
vm.albums = [];
for(var album in responseData.data)
$scope.vm.albums.push(album);
$log.debug(angular.toJson(responseData, true));
})
}
function getAlbumTracks(album, index){
$http.get('http://localhost:8080/api/albums/'+album).success(function(trackResponse){
//parse each album and get the track list
//alert('Function getAlbumTracks () called');
vm.showingAlbumIndex = index;
vm.albums.tracks = [];
for(var i = 0; i<trackResponse.tracks.length; i++)
vm.albums.tracks.push(trackResponse.tracks[i].title);
$log.debug(vm.albums.tracks);
})
}
function displayForm(track, index){
// display the form for that track only
}
function newFunction(name){
$log.debug("Hello " + name);
}
}
})();
Custom directive.js
(function (){
'use strict';
angular.module('app.fileUploadForm').directive('metadataForm', metadataForm);
function metadataForm(){
return {
restrict: 'EA',
templateUrl: 'app/fileUploadForm/metadata-form.html'
};
};
})();
metadata-form.html file:
<div ng-show="showForm">
<form name="uploadForm" ng-controller="FileUploadFormController as uploadCtrl">
<br>UPC:<br>
<input type="text" ng-model="UPC">
<br>
<br>Artist:<br>
<input type="text" ng-model="artist">
<br>
<br>Genre:<br>
<input type="text" ng-model="genre">
<br>
<br>Album:<br>
<input type="text" ng-model="album">
<br>
<br>Hold Date:<br>
<input type="text" ng-model="holddate">
<br>
<br>SomeField:<br>
<input type="text" ng-model="somefield">
</form>
<!-- trying the date picker here
<h4>Standard date-picker</h4>
<md-datepicker ng-model="myDate" md-placeholder="Enter date"></md-datepicker>
--><br>
<button class="btn btn-primary block m-b" ng-click="uploadFile()">Send to Ingestion</button>
Any idea how to achieve this ?
To begin with, I think your custom directive shouldn't use the same controller of your first code. Remove ngController directive in metadataForm.
Use data binding to get track information when the directive is called:
(function (){
'use strict';
angular.module('app.fileUploadForm').directive('metadataForm', metadataForm);
function metadataForm(){
return {
restrict: 'EA',
templateUrl: 'app/fileUploadForm/metadata-form.html',
scope: {}, // Isolated scope
bindToController: {
track: '='
}
controller: controllerFunc
controllerAs: 'vm'
};
function controllerFunc() {
var vm = this;
// Your track is accessible at vm.track
}
};
})();
You have to change the ng-model in metadataForm template to bind your data with data from your controller.
To make the metadataForm directive appear on click, you could use ng-ifdirective:
// HTML
<div class="wrapper wrapper-content">
<div>
<ul>
<li ng-repeat="album in vm.albums">
<a ng-click="vm.getAlbumTracks(album, $index)">{{album}}</a>
<ul ng-show="$index === vm.showingAlbumIndex">
<li ng-repeat="track in vm.albums.tracks"><a ng-click="vm.displayForm(track)">{{track}}</a></li>
</ul>
</li>
</ul>
<metadata-form ng-if="vm.isFormDisplayed" track="vm.displayedTrack"></metadata-form>
<a ng-click="vm.newFunction('RAVI')">Click Me!</a>
</div>
And in the controller you described:
function displayForm(track, index){
vm.isFormDisplayed = true;
vm.displayedTrack = track;
}
I am setting a boolean value to true after user logs in and I want to update the login button status to logout. I tried using ng-show but apparently its not working.
States:
myApp.config(function ($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/Home");
var header = {
templateUrl: 'commonViews/Header.html',
controller: function ($scope) {
}
};
var footer = {
templateUrl: 'commonViews/Footer.html',
controller: function ($scope) {
}
};
// ui router states
$stateProvider
.state('Home', {
url: "/Home",
views: {
header: header,
content: {
templateUrl: 'views/HomePage.html',
controller: function ($scope) {
}
},
footer: footer
}
})
.state('LoggedIn', {
url: "/LoggedIn",
views: {
'header': header,
'content': {
templateUrl: 'views/LoggedIn.html',
controller: function ($scope) {
}
},
'footer': footer
}
});
});
UserService:
myApp.factory('UserService', function ($http, $localStorage, AuthenticationService) {
return {
logIn: function (email, password) {
return $http.post('rs/loginResource/login', {email: email, password: password})
.then(function (data) {
AuthenticationService.isLogged = true;
alert("Authentication loggedIn inside login controller: " + AuthenticationService.isLogged);
return data;
})
.catch(function (error) {
console.log(error);
});
},
logOut: function () {
if (AuthenticationService.isLogged) {
AuthenticationService.isLogged = false;
delete $localStorage.token;
}
}
};
});
myApp.factory('AuthenticationService', function () {
var auth = {
isLogged: false
};
return auth;
});
Login controller:
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$sessionStorage', '$state', '$window', 'UserService', 'AuthenticationService', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state, $window, UserService, AuthenticationService)
{
$scope.token = "";
$scope.$storage = $localStorage;
$scope.loginForm = function (email, password) {
if (email !== undefined && password !== undefined) {
UserService.logIn(email, password).then(function (response) {
$localStorage.token = response.data.token;
if ($localStorage.token) {
$state.go('LoggedIn');
alert("scope loggedIn inside login controller: " + AuthenticationService.isLogged);
}
}).catch(function (status, data) {
console.log(status);
console.log(data);
});
}
$scope.logout = function logout() {
UserService.logOut().success(function () {
$state.go('/');
}).error(function (status, data) {
console.log(status);
console.log(data);
});
};
};
}]);
index.html:
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head></head>
<body>
<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>
</body>
</html>
Header html:
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<b>Logout</b>
<b>Login</b> <span class="caret"></span>
<ul id="login-dp" class="dropdown-menu">
<!---------------------------------Login Controller Here------------------------------------->
<li>
<div class="row">
<div class="col-md-12">
<form class="form" role="form" method="post" ng-controller="loginController" ng-submit="loginForm(email, password)" accept-charset="UTF-8" id="login-nav">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail2">Email address</label>
<input type="email" class="form-control" ng-model="email" id="exampleInputEmail2" placeholder="Email address" required>
</div>
<div class="form-group">
<label class="sr-only" for="exampleInputPassword2">Password</label>
<input type="password" class="form-control" id="exampleInputPassword2" ng-model="password" placeholder="Password" required>
<div class="help-block text-right">Forget the password ?</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</div>
</form>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
After user is logged in, it changes the status to logout for split second and then back to login status again. I am not sure what's going wrong?
Add AuthenticationService to the scope of your controller,
$scope.AuthenticationService = AuthenticationService;
and remove $scope from your view/template
<ul class="nav navbar-nav navbar-right" ng-controller="loginController">
<li class="dropdown">
<b>Logout</b>
<b>Login</b> <span class="caret"></span>
</li>
Put an isLoggedIn() function in your header controller:
myApp.config(function ($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/Home");
var header = {
templateUrl: 'commonViews/Header.html',
controller: function ($scope, AuthenticationService) {
$scope.isLoggedIn = function() {
return AuthenticationService.isLogged;
});
}
};
var footer = {
templateUrl: 'commonViews/Footer.html',
controller: function ($scope) {
}
};
// ui router states
And in your header HTML use that function:
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
ng-show="isLoggedIn()" ng-click="logout()"><b>Logout</b>
</a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
ng-show="!isLoggedIn()">
<b>Login</b> <span class="caret"></span>
</a>
UPDATE
Your login controller's scope is a child of the header controller's scope. Your ng-show directives are not in your login controller's scope. By putting functions that query the AuthenticationService.isLogged state in the correct scope, the ng-show directives should work properly.
There are 2 issues in your code
AuthenticationService.isLogged
is not updated after successful login with UserService
You don't need to have $scope in your templates as any Angular expression that you pass in your HTML template will be resolved against the current scope.
I would suggest not to expose your services onto your view layer. Just add a property isLoggedIn on your scope which will determine whether to show Login or Logout buttons.
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$sessionStorage', '$state', '$window', 'UserService', 'AuthenticationService', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state, $window, UserService, AuthenticationService)
{
$scope.token = "";
$scope.$storage = $localStorage;
// new property to hold login status
$scope.isLoggedIn = false;
$scope.loginForm = function (email, password) {
if (email !== undefined && password !== undefined) {
UserService.logIn(email, password).then(function (response) {
$localStorage.token = response.data.token;
if ($localStorage.token) {
// cache the login status for use in other controllers
AuthenticationService.isLogged = true;
// update the scope for use in templates
$scope.isLoggedIn = true;
$state.go('LoggedIn');
}
}).catch(function (status, data) {
console.log(status);
console.log(data);
});
}
$scope.logout = function logout() {
UserService.logOut().success(function () {
// cache the login status for use in other controllers
AuthenticationService.isLogged = false;
// update scope for use in templates
$scope.isLoggedIn = false;
$state.go('/');
}).error(function (status, data) {
console.log(status);
console.log(data);
});
};
};
}]);
With this, in your templates, you can just check for isLoggedIn like below
<ul class="nav navbar-nav navbar-right" ng-controller="loginController">
<li class="dropdown">
<a href="#" class="dropdown-toggle"
data-toggle="dropdown"
ng-show="isLoggedIn"
ng-click="logout()">
<b>Logout</b></a>
<a href="#" class="dropdown-toggle"
data-toggle="dropdown"
ng-show="!isLoggedIn">
<b>Login</b> <span class="caret"></span>
</a>
</li>
</ul>
would anyone be able to help me on this issue I am having?
I have a NavCtrl for manage my active tag, I was able to change the active tab when click on the menu item, however when I click on the link in the body views, it take me to the page I want to, but the active tag is not change.
//controller for nevigation menu
sp.controller('NavCtrl', ['$scope', 'auth', '$window','$rootScope', function ($scope, auth, $window,$rootScope) {
$scope.LogOut = auth.logOut;
$scope.isLoggedIn = auth.isLoggedIn;
$scope.tab = $rootScope.navTav;
$scope.toTop = function(){
$window.scrollTo(0, 0);
};
}]);
I try to use the $rootScope to set the navTab, but it's still not working
//setting root scope
sp.run(function($rootScope) {
$rootScope.navTav = 1;
})
ui-Router
.state('qaanswer', {
url: '/qa/{quesId}',
views: {
view50': {
templateUrl: './qa/qaanswer.html',
controller: 'QAAnswerCtrl'
},
'view60': {
templateUrl: './shareviews/activityupdates.html',
controller: 'HomeCtrl'
}
},
onEnter:['$rootScope',function($rootScope){
$rootScope.navTav = 5;
}]
Thank you so much for the help
Update HTML :
<body ng-controller="NavCtrl">
<!-- Desktop Menu -->
<div>
<div>
<ul>
<a href="#/home" ng-class="{active: navTab === 1}" ng-click="navTab = 1">
<li>Home</li>
</a>
<a href="#/qa" ng-class="{active: navTab === 2}" ng-click="navTab = 2">
<li>QA</li>
</a>
</ul>
</div>
</div>
<div>
<div>
<div class="row">
<div ui-view="view50"></div>
<div ui-view="view60"></div>
</div>
</div>
</div>
</body>
Working plunker
You can simplify your implementation and have no issues. Simply use the $rootScope variable directly in your template along side ng-class like so:
<body ng-controller="NavCtrl">
<a ng-class="{red: $root.navTab===0}" ui-sref="first">first</a>
<a ng-class="{red: $root.navTab===1}" ui-sref="second">second</a>
<div ui-view></div>
</body>
Then update $rootScope in your controllers.
.controller('NavCtrl', function($scope, $rootScope) {});
.controller('FirstCtrl', function($scope, $rootScope) {
$rootScope.navTab = 0;
});
.controller('SecondCtrl', function($scope, $rootScope) {
$rootScope.navTab = 1;
});
Your states get to stay relatively simple:
.state('first', {
url: '/first',
templateUrl: 'first.html',
controller: 'FirstCtrl'
})
.state('second', {
url: '/second',
templateUrl: 'second.html',
controller: 'SecondCtrl'
})
plunker
Ideally you would make a directive for such a task, and avoid using $rootScope. A simple way to do this is to broadcast a message whenever you land on a new page, then listen on that event in your tab directive and flip the correct tab as active.
I'm trying to show the navigation bar once the user logs in successfully. but the navigation-bar is still hidden even after the user logs in.
here is a part of the index.html
<header id="Header1" data-ng-controller="navigationController">
<!-- Navigation bar -->
<nav class="navbar navbar-inverse" id="nav1" ng-hide="isConnected">
<div class="collapse navbar-collapse">
<ul id="Ul1" class="nav navbar-nav" style="color: white; font-weight: bolder; font-family: Arial; border-radius: 5px;">
<!-- <li class="nav navbar-brand" id="Li1" style="padding: 0px 0px 0px 0px;">
<img src="favicon.ico" height="20" width="20" />
</li>-->
<li id="Li2" data-ng-class="{'active':isActive('/home')}">
<a data-original-title="Home page." class="disable-click" href="#/home">Home</a>
</li>
<li data-ng-class="{'active':isActive('/demo')}">
<a data-original-title="Demonstration page." class="disable-click" href="#/demo">Demonstration</a>
</li>
</ul>
</div>
</nav>
</header>
the controller navigationController.js is
'use strict';
app.controller('navigationController',
function ($scope, $location, $rootScope, AuthenticationService) {
debugger;
$scope.isActive = function (path) {
return $location.path().substr(0, path.length) == path;
};
$scope.isConnected = !($rootScope.globals.currentUser);
console.log($scope.isConnected);
});
i store the current user in this service
service.SetCredentials = function (username, password) {
var authdata = Base64.encode(username + ':' + password);
$rootScope.globals = {
currentUser: {
username: username,
authdata: authdata
}
};
$http.defaults.headers.common['Authorization'] = 'Basic ' + authdata;
$cookieStore.put('globals', $rootScope.globals);
};
the binding is not working after the login, except when i refresh the menu is shown (when the cookie has became full). any solution please
Your isConnected property is only evaluated once when the controller is instantiated. When the user logs in there is nothing to re-evaluate isConnected
You could set up a watch like this to have it re-evaluate:
'use strict';
app.controller('navigationController',
function ($scope, $location, $rootScope, AuthenticationService) {
debugger;
$scope.isActive = function (path) {
return $location.path().substr(0, path.length) == path;
};
$rootScope.$watch('globals', function(newVal, oldVal) {
$scope.isConnected = !($rootScope.globals.currentUser);
}, true);
});
note it might be possible you can add the watch directly to $scope instead of $rootScope as the globals property should be inherited prototypically, though I haven't tested this to verify
Try this
'use strict';
app.controller('navigationController',
function ($scope, $location, $rootScope, AuthenticationService) {
...
$scope.isConnected = function() {
return !($rootScope.globals.currentUser);
};
});
And do not change ng-hide value to ng-hide="isConnected()", keep it as ng-hide="isConnected"
<nav class="navbar navbar-inverse" id="nav1" ng-hide="isConnected">
...
I have a work and stuck it 2 days. Hope everyone know angularjs help me :).
I need to force a change html when have a change on model. Example:
This is html code:
<!--CAKE LIST-->
<div id="cakelist" ng-controller="CakeListCtrl">
<ul class="thumbnails cake-rack" cakes="cakes" ng-model="cakesModel">
<li class="pull-left cake-unit" ng-repeat="cake in cakes" cake="cake">
<div class="thumbnail">
<a href="{{cake.link}}">
<img ng-src="{{cake.avatar}}" alt="{{cake.title}}" class="img img-rounded img-polaroid" />
</a>
<h5 class="pull-left">
{{cake.title}}
</h5>
Shared
<div class="clearfix"></div>
<ul class="attrs unstyled">
<li>
<div class="pull-left">Mã sản phẩm</div>
<span class="pull-right">{{cake.type}}</span>
</li>
</ul>
</div>
</li>
</ul>
<input type="button" class="btn btn-primary" value="add more cake" class="cake-more" ng-click="addCake()" />
<input type="button" class="btn btn-danger" value="clear cake" class="cake-clear" ng-click="clear()" />
<img alt="Loading" src="/imagesroot/ajax-loader-1.gif" loading-stage="loadingStage" class="cake-loading"/>
</div>
now a have a menu outside of controller:
<div id="cake-catalog" class="cake-catalog">
<ul class="nav">
<li class="active">
<a cake-menu-unit href="sacmscategory50c2302b7ff0a">Nhân vật hoạt hình</a>
</li>
<li>
<a cake-menu-unit href="sacmscategory50c2308717a84">Động vật</a>
</li>
<li>
<a cake-menu-unit href="sacmscategory50c2309da00f6">Tạo hình 3D</a>
</li>
<li>
<a cake-menu-unit href="sacmscategory50c230ba08d9d">Các mẫu hình khác</a>
</li>
</ul>
</div>
I have angular module for add and clear:
var CakeList = angular.module('CakeList', ['ngResource']);
CakeList.service('CakeService', function($rootScope) {
var cakedata = [{avatar:"test", title: "test2"}];
$rootScope.loadCake = false;
var bf = function() { $rootScope.loadCake=true; };
var at = function() { $rootScope.loadCake=false; };
return {
cakes: function() {
bf();
at();
return cakedata;
},
addCake: function() {
bf();
cakedata.push(cake);
at();
},
clear: function() {
cakedata = []; console.log('clear');
}
};
});
CakeList.directive('cakeCatalog', function($rootScope, CakeService) {
var clickfn = function(e) {
e.preventDefault();
CakeService.clear();
};
var nonclickfn = function(e) {
e.preventDefault();
console.log('nonclickfn');
};
return {
restrict: "C",
link: function(scope, element, attrs) {
$rootScope.$watch('loadCake', function(newValue, oldValue) {
if (newValue===true) {
element.find('a').off('click').on('click', nonclickfn);
}
else {
element.find('a').off('click').on('click', clickfn);
}
});
}
};
But when runtime, i put click on a element of menu then the list cake not clear, even i check console.log in console box and see the cakedata really clear!. Can you help me this case ? :)
First of all, the design seems a bit weird by using everywhere $rootScope (among other things). But that's not the cause of the problem. The problem is the $watch which is not correct.
First of all, use loadCake as an object instead of a primitive type:
var loadCake = { loaded: false};
Use the objectEquality parameter in your $watch statement:
$rootScope.$watch('loadCake', function(newValue, oldValue) {
if (!newValue) return;
if (newValue.loaded === true) {
element.find('a').off('click').on('click', nonclickfn);
}
else {
element.find('a').off('click').on('click', clickfn);
}
}, true);