Angular beginner here. I'm trying to basically have my link be active once I'm on a given page. Found quite couple of examples none of which work, so it must be that I'm doing wrong.
This is what I've been trying (controller) :
angular.module('MyApp')
.controller('HomeCtrl', ['$scope', function ($scope) {
$('body').addClass('homepage');
$scope.isActive = function(route) {
return route === $location.path();
}
}]);
Html :
<li "ng-class" = "{active:isActive('/') || isActive('/home')}">
Home
</li>
<li "ng-class" = "{active:isActive('/about')}">
About
</li>
<li "ng-class" = "{active:isActive('/contact')}">
Contact
</li>
Application itself :
var app = angular
.module('MyApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'templates',
'ng-token-auth'
]).config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider
.when('/home', {
templateUrl: 'home.html',
controller: 'HomeCtrl'
})
.when('/', {
templateUrl: 'home.html',
controller: 'HomeCtrl'
})
.when('/contact', {
templateUrl: 'contact.html',
controller: 'ContactCtrl'
})
.when('/about', {
templateUrl: 'about.html',
controller: 'AboutCtrl'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
}])
So no matter on which page I'm located at, the ng-class does nothing with no errors in the console. However if I do this for home:
<li "ng-class" = "{active:true}">
Home
</li>
Then I get active class on my link, and this is the output :
<li ng-class="{active:true}" class="active">
Home
</li>
What am I doing wrong here? Why doesn't it interpolate the function isActive as it should?
You cannot have the logic to check the active link inside your HomeCtrl as it is one of the routes. When other routes are loaded there is no HomeCtrl loaded.
There should be controller defined outside the ng-view, such as RootCtrl. The isActive function should be added to it.
Since the child view scope would have access to parent scope, you can use the isActive in the child views normally.
Update:
Consider the html
<body ng-controller='RootCtrl'>
<div ng-view></div>
</body>
Add the isActive function on the RootCtrl.
Related
So here is my logout on ng-click: (my view)
<div class="navbar navbar-default"><div class="container">
<div id="navbar-main">
<ul class="nav navbar-nav">
<li>Home</li>
<li ng-show="navvm.isLoggedIn" ng-hide="navvm.logout">{{ navvm.currentUser.name }}</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-hide="navvm.isLoggedIn">Sign in</li>
<li ng-show="navvm.isLoggedIn"><a ng-click="logOut()" href="">Logout</a></li>
</ul>
</div>
Then i'm trying to remove the localStorage by removing the token like so: (controller)
(function () {
angular
.module('meanApp')
.controller('logoutCtrl', logoutCtrl);
logoutCtrl.$inject = ['$location', '$window'];
function logoutCtrl($location, $window) {
logout = function() {
$window.localStorage.removeItem('mean-token');
};
}
})();
(controller):
(function () {
angular.module('meanApp', ['ngRoute']);
function config ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '/home/home.view.html',
controller: 'homeCtrl',
controllerAs: 'vm'
})
.when('/register', {
templateUrl: '/auth/register/register.view.html',
controller: 'registerCtrl',
controllerAs: 'vm'
})
.when('/login', {
templateUrl: '/auth/login/login.view.html',
controller: 'loginCtrl',
controllerAs: 'vm'
})
.when('/profile', {
templateUrl: '/profile/profile.view.html',
controller: 'profileCtrl',
controllerAs: 'vm'
})
.when('/logout', {
templateUrl: '/home/home.view.html',
controller: 'logoutCtrl',
})
.otherwise({redirectTo: '/'});
// use the HTML5 History API
$locationProvider.html5Mode(true);
}
function run($rootScope, $location, authentication) {
$rootScope.$on('$routeChangeStart', function(event, nextRoute, currentRoute) {
if ($location.path() === '/profile' && !authentication.isLoggedIn()) {
$location.path('/');
}
});
}
angular
.module('meanApp')
.config(['$routeProvider', '$locationProvider', config])
.run(['$rootScope', '$location', 'authentication', run]);
})();
Whenever I try to logout the localStorage is still defined. I've tried clearing the storage. Tried deleting it. Maybe i'm not doing the angular right. I'm new to all of this so please help. Thank you!
You have to inject the $scope variable into your controller and define logout function on the $scope
logoutCtrl.$inject = ['$location', '$window', '$scope'];//injecting the $scope
function logoutCtrl($location, $window, $scope) {
//defining logout function on the $scope
$scope.logout = function() {
$window.localStorage.removeItem('mean-token');
};
}
Also you have a typo. Remove the 'O' uppercase on logOut()
<a ng-click="logout()" href="">Logout</a>
Try without window.
localStorage.removeItem('mean-token');
Fiddle
Did you try to move logout function to homeCtrl, to check if it works there?
When I click on the Home link, the goTo function is executed. However, it redirects me to a blank page like so:
When I click on the browser's back button, it redirects me to the page I wanted to go to (firstPage).
Any suggestions on what I am doing wrong?
HTML:
<footer ng-controller = "footerLink">
Home
About us
Our Team
Blog
Services
Portfolio
Contact
Sitemap
</footer>
JS
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
}).
when('/buttonView', {
templateUrl: 'buttonView/buttonView.html',
controller: 'buttonViewCtrl'
}).
when('/firstPage', {
templateUrl: 'view2/view2.html',
controller: 'footerLink'
}).
when('/home', {
templateUrl: 'view1/view1.html',
controller: 'logo'
});
}])
.controller('footerLink', ['$scope', '$location', function($scope, $location) {
$scope.goTo = function (url) {
$location.path(url);
};
}])
UPDATE
I directly redirected the anchor to the firstPage route instead of calling another function. Here is what I changed to make it work:
<footer ng-controller = "footerLink">
Home
About us
Our Team
Blog
Services
Portfolio
Contact
Sitemap
</footer>
it is because you do not have a redirection rule or a route configuration for '/' you can redirect the user to home if there is no matching route.
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
}).
when('/buttonView', {
templateUrl: 'buttonView/buttonView.html',
controller: 'buttonViewCtrl'
}).
when('/firstPage', {
templateUrl: 'view2/view2.html',
controller: 'footerLink'
}).
when('/home', {
templateUrl: 'view1/view1.html',
controller: 'logo'
}).otherwise({redirectTo: '/home'});
}])
.controller('footerLink', ['$scope', '$location', function($scope, $location) {
$scope.goTo = function (url) {
$location.path(url);
}; // this function is not really required
}]);
and instead of creating another function to redirect user you can use the use the href on html as you are not doing any other processing there except redirecting user.
<footer ng-controller = "footerLink">
Home
About us
Our Team
Blog
Services
Portfolio
Contact
Sitemap
</footer>
Below is my app.js file
angular
.module('repoApp', [
'ngAnimate',
'ngAria',
'ngCookies',
'ngMessages',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'ui.bootstrap',
'ui.router'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.when('/login', {
templateUrl: 'views/loginPage.html',
controller: 'loginCtrl'
})
.otherwise({
redirectTo: '/'
});
});
angular
.module('loginState',['ui.router']);
Below is my states file
angular
.module('repoApp')
.config(function ($stateProvider) {
$stateProvider.state('home1', {
url:'/home1',
templateUrl: 'views/modals/test.html'
})
.state('secondState',{
url:'/secondState',
templateUrl: 'views/modals/secondStateTest.html'
});
});
The problem is, using my html i navigate to login page.
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li><a ng-href="#/about">About</a></li>
<li><a ng-href="#/">Contact</a></li>
<li class="loginShift"><a ng-href="#/login">Login</a></li>
</ul>
but I am trying to hit the state as soon my flow hit the controller
angular.module('repoApp')
.controller('loginCtrl', function ($scope,$modal,$state) {
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
$state.go('home1');
$scope.openDialog = function () {
$modal.open({
keyboard: 'static',
templateUrl: 'views/login/loginCred.html',
});
};
});
but I am not able to hit the home state.
If I change my states file i.e
$stateProvider.state('home1', {
url:'/login',
templateUrl: 'views/modals/test.html'
})
here I changed URL. It works fine now.
I have a template from where I want to navigate to a next state
<div>
<button data-ng-click="openDialog()">open ME!</button>
<div><a ui-sref="secondState">click here</a></div>
</div
but as soon I click this anchor tag it navigates me back to home page. ie not to the state I intend to go.
The main issue is URL(i guess) any help will be appreciated.
You shouldn't use both ngRoute and UI-router. Here's a sample code for UI-router:
repoApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html",
controller: 'YourCtrl'
})
.state('state2', {
url: "/state2",
templateUrl: "partials/state2.html",
controller: 'YourOtherCtrl'
});
$urlRouterProvider.otherwise("/state1");
});
//etc.
You can find a great answer on the difference between these two in this thread: What is the difference between angular-route and angular-ui-router?
You can also consult UI-Router's docs here: https://github.com/angular-ui/ui-router
Plunker: http://plnkr.co/edit/0efF1Av4lhZFGamxKzaO?p=preview
Below is my header, there is an ng-show="cornerLogo" which I only want to be set true on the about, login and register views, but false the home view.
<body id="body_id"
ng-app="myApp"
ng-controller="HomeCtrl">
<header>
<section ng-show="cornerLogo">
<h1>Logo</h1>
</section>
<nav id="main_nav">
<ul>
<li><a ui-sref="about">About</a></li>
<li><a ui-sref="login">Sign In</a></li>
<li><a ui-sref="register">Create Account</a></li>
</ul>
</nav>
</header>
<ui-view></ui-view>
So it works in my HomeCtrl because that is the main controller on the page.
var app = angular.module('app-home', [])
.controller('HomeCtrl', ['$scope', function($scope) {
$scope.cornerLogo = false;
}]);
However when I switch to the about, login or register views I lose that $scope
Is there a way somehow to have a global var set somewhere in my stateProvider for ui-router? Otherwise, how would you go about this issue?
var app = angular.module('bitAge',
['ui.router',
'app-header',
'app-home',
'app-about',
'app-login',
'app-register'])
.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '_views/home.html',
controller: 'HomeCtrl',
})
.state('about', {
url: '/about',
templateUrl: '_views/about.html',
controller: 'AboutCtrl'
})
.state('login', {
url: '/login',
templateUrl: '_views/login.html',
controller: 'LoginCtrl'
})
.state('register', {
url: '/register',
templateUrl: '_views/register.html',
controller: 'RegisterCtrl'
});
// default view:
$urlRouterProvider.otherwise('/home');
}]);
Apart from my comments in the question, to fix your issue you can take this approach.
You have HomeCtrl specified as bound controller in the state registration of home partial. So instead create a main controller for your application. So that you keep the responsibilities separated out. Inject $state and expose a method called hideLogo and use $state.is to determine the logic to show/hide the logo.
i.e:
var app = angular.module('app-home')
.controller('MainCtrl', ['$scope', '$state', function($scope, $state) {
$scope.hideLogo = function(){
return $state.is('home');
}
}]);
In the index html use MainCtrl as your main controller for the app.
<body ng-app="myApp" ng-controller="MainCtrl">
<header>
<section
ng-hide="hideLogo()">
<h1>Corner Logo</h1>
</section>
Plnkr
If you want to use $state directly on the view you would need to inject it in MainCtrland set $state on the $scope object so that you can use it directly. Though i highly recommend not to use this technique, you should not expose state in the scope object and ultimately in the view. Just expose only what is needed in the viewmodel.
i.e in the MainCtrl :
var app = angular.module('app-home')
.controller('MainCtrl', ['$scope', '$state', function($scope, $state) {
$scope.$state= $state;
}]);
and just use it on the view as:
<section
ng-hide="$state.is('home')">
You can check your current state and depends on that, show or not your logo.
<section ng-show="$state.includes('home')">
<h1>Logo</h1>
</section>
Also, your anchor elements to navigate, should be like this <a ui-sref="about">About</a> and so on, because if you use normal href attribute, angular wont change state.
Also, you need to inject $state in your main module and then you can use $state module
var app = angular.module('myApp',
['ui.router',
'app-home',
'app-about']).run(function ($state,$rootScope) {
$rootScope.$state = $state;
})
UPDATE:
Here is the punklr with the answer
I am a rank beginner with angularJS and I'm developing the ui for a single-page app in angularJS using node/bower/grunt and I have installed angular-ui-bootstrap and the route and event utils from angular-ui-utils.
I've used ng-class={active:$uiRoute} on the menu items but when a menu item is selected the active class is not applied...does $uiRoute handle this or do I need to code it separately?
Apologies for asking a dumb question...
Here is the code:
`<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li ui-route="/" ng-class="{active:$uiRoute}">Home</li>
<li ui-route="/about" ng-class="{active:$uiRoute}">About</li>
<li ui-route="/other" ng-class="{active:$uiRoute}">Other</li>
</ul>
</div>
...
<script src="bower_components/angular-ui-utils/modules/route/route.js"></script>
<script src="bower_components/angular-ui-utils/modules/event/event.js"></script>`
And
angular.module('myApp', ['ngRoute','ngResource','ui.bootstrap'])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.when('/other', {
templateUrl: 'views/other.html',
controller: 'OtherCtrl'
})
.otherwise({
redirectTo: '/'
});
})
Looking through the ui-utils docs, it appears you have not injected the module dependency. Change your myApp to inject ui.utils
angular.module('myApp', [
'ngRoute',
'ngResource',
'ui.bootstrap',
'ui.utils'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.when('/other', {
templateUrl: 'views/other.html',
controller: 'OtherCtrl'
})
.otherwise({
redirectTo: '/'
});
});
add ng-class="{'active':isActive('/about')}"
.run([ '$rootScope', '$location', function($rootScope, $location, ) {
$rootScope.isActive = function(path) {
if ($location.path() && $location.path().substring(0, path.length) == path) {
return true;
}
return false;
}
}
I advise you tu use UI router with named states.
Your router will looks like :
angular
.module('myApp', ['ui.router'])
.config(($stateProvider, urlRouterProvider) => {
$stateProvider
.state('index', {
url: '/',
templateUrl: 'views/main.html',
controller: 'MainCtrl',
})
.state('index.about', {
url: 'about/'
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
});
$urlRouterProvider.otherwise('/');
});
and you will be able to user ui-sref-active directive in your template like :
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li ui-sref-active="{ 'active': 'index' }">
Home
</li>
<li ui-sref-active="{ 'active': 'index.about' }">
About
</li>
</ul>
</div>