Reputation: 401
I'm new to Angular.js, so I'm sure there is a very simple solution to this, and I'm surprised there isn't a bunch of tutorials that cover this question.
(There are plenty that cover pagination of a long list of results - but my problem seems quite different.)
I have successfully implemented routes for a number of pages within my "single page application" / website. These pages have a natural order, so I am trying to implement Previous and Next buttons (or links) in the header, so that the Next button cycles through Home > Page 1 > Page 2 > Page 3 > Home, and the previous button goes backwards from Home > Page 3 > Page 2 > Page 1 > Home.
Having read some relevant-ish articles, tutorials, examples, and StackOverflow Q&As I've tried a few methods that I thought might work, but the Prev / Next buttons do not dynamically update as intended when the route / ng-view changes.
i.e. in my simplified code below (with Home, About and Contact pages), the targets of the Previous / Next buttons and their respective functions nextPage()
and prevPage()
always relate to the "Home" page's previous and next pages, even when another page has been navigated to.
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="script.js"></script>
</head>
<!-- define angular controller -->
<body ng-controller="mainController">
<nav class="navbar navbar-default">
<div class="container">
<button class="btn" ng-click="prevPage()">Previous</button>
<button class="btn" ng-click="nextPage()">Next</button>
</div>
</nav>
<div id="main">
<div ng-view></div>
</div>
</body>
</html>
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
// Page routes
.when('/', { templateUrl : 'pages/home.html', controller : 'mainController' })
.when('/about', { templateUrl : 'pages/about.html', controller : 'aboutController' })
.when('/contact', { templateUrl : 'pages/contact.html', controller : 'contactController' })
.otherwise( {redirectTo:'/'} );
});
// create the controller and inject Angular's $scope
app.controller('mainController', function($scope, $location) {
$scope.nextPage = function() { $location.path('/about'); };
$scope.prevPage = function() { $location.path('/contact'); };
});
app.controller('aboutController', function($scope, $location) {
$scope.nextPage = function() { $location.path('/contact'); };
$scope.prevPage = function() { $location.path('/'); };
});
app.controller('contactController', function($scope, $location) {
$scope.nextPage = function() { $location.path('/contact'); };
$scope.prevPage = function() { $location.path('/'); };
});
Here's a Plunker (it's based based on this one).
What is the best way of achieving this?!
Upvotes: 2
Views: 2289
Reputation: 2687
Try this:
This example work with one controller for router
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/home', { templateUrl : 'pages/home.html', controller : 'mainController' })
.when('/about', { templateUrl : 'pages/about.html', controller : 'mainController' })
.when('/contact', { templateUrl : 'pages/contact.html', controller : 'mainController' })
.otherwise( {redirectTo:'/home'} );
});
// create the controller and inject Angular's $scope
app.controller('mainController', function($scope, $rootScope, $location) {
$scope.nextPage = function() {
if(!$rootScope.currentPage || $rootScope.currentPage == 0){
$rootScope.currentPage = 1;
$location.path('/about');
}else if($rootScope.currentPage == 1){
$rootScope.currentPage = 2;
$location.path('/contact');
}
else if($rootScope.currentPage == 2){
$rootScope.currentPage = 0;
$location.path('/home');
}
}
$scope.prevPage = function() {
if(!$rootScope.currentPage || $rootScope.currentPage == 0){
$rootScope.currentPage = 2;
$location.path('/contact');
}else if($rootScope.currentPage == 1){
$rootScope.currentPage = 0;
$location.path('/home');
}else{
$rootScope.currentPage = 1;
$location.path('/about');
}
};
});
Upvotes: 1
Reputation: 1723
The reason why it behaves like this, is because the scope object you define in your controllers, is only inside the ng-view
, and outside of it, the scope is bound to the main controller (since you passed it in in the ng-controller
).
you can see it here http://plnkr.co/edit/sh5JcJs82c7uIiVg6Skg?p=preview
where the hello
variable, is different when it's outside the ng-view
.
My sulotion is you should use the $rootScope
, here's a working plunker: http://plnkr.co/edit/krs7mzcIVktXxFPvG44R?p=preview
(btw, another issue, you did in the contact controller wrong, and I fixed it).
Upvotes: 1
Reputation: 10374
The problem is the buttons are bound to functions on the mainController
, which are not the ones being changed when the /about
and /contact
routes are being shown.
You could add another homeController
for the /
route and have all the three route controllers change the mainController
's nextPage
and prevPage
functions appropriately.
Like:
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
// Page routes
.when('/', { templateUrl : 'pages/home.html', controller : 'homeController' })
.when('/about', { templateUrl : 'pages/about.html', controller : 'aboutController' })
.when('/contact', { templateUrl : 'pages/contact.html', controller : 'contactController' })
.otherwise( {redirectTo:'/'} );
});
// create the controller and inject Angular's $scope
app.controller('mainController', function($scope, $location) {
$scope.nextPage = function() { $location.path('/about'); };
$scope.prevPage = function() { $location.path('/contact'); };
});
app.controller('homeController', function($scope, $location) {
$scope.$parent.nextPage = function() { $location.path('/about'); };
$scope.$parent.prevPage = function() { $location.path('/contact'); };
});
app.controller('aboutController', function($scope, $location) {
$scope.$parent.nextPage = function() { $location.path('/contact'); };
$scope.$parent.prevPage = function() { $location.path('/'); };
});
app.controller('contactController', function($scope, $location) {
$scope.$parent.nextPage = function() { $location.path('/'); };
$scope.$parent.prevPage = function() { $location.path('/about'); };
});
Working Plunker: http://plnkr.co/edit/8Q2IIn?p=preview
Upvotes: 1