On certain views I want a sidebar and header, and some I do not. Using AngularJS, what is the best approach to achieve this.
My current solution in mind is to use ng-if on the sidebar and header DIV, and in my Controllers, set a $scope variable to be set to true or false depending on the views I want the sidebar and header to appear.
A concrete example would be Youtube.com. On Youtube's homepage, notice there is a sidebar and a sub-header with the filters: "What to Watch" and "Music" in it. However, on any video page, the sidebar and sub-header doesn't exist. I want to achieve that in AngularJS.
index.html
<html ng-app="demoApp">
<body ng-controller="demoAppMainController">
<header>
<ng-include src="'./partials/mainHeader.html'"></ng-include>
<ng-include ng-if="showSubHeader" src="'./partials/mainSubHeader.html'"></ng-include>
</header>
<main>
<ng-view></ng-view>
</main>
</body>
</html>
discussionBoard.html
<div class="discussionBoard" ng-controller="DiscussionBoardController">
<h2>DiscussionBoard</h2>
</div>
controllers.js
var demoAppControllers = angular.module('demoAppControllers', []);
demoAppControllers.controller('demoAppMainController', ['$scope', function($scope) {
$scope.showSubHeader = true;
}]);
opinionLensControllers.controller('DiscussionBoardController', ['$scope', function($scope) {
$scope.showSubHeader = false;
}]);
Instead of doing it in controller level, I would configure that in route level. And will listen to the $routeChangeSuccess event and update the $rootScope.
demoAppControllers.config(function ($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'home.html',
controller: 'HomeController',
showHeader : true
}).
when('/about', {
templateUrl: 'discuss.html',
controller: 'DiscussionBoardController',
showHeader : false
}).
otherwise({
redirectTo: '/home'
});
}).
run(['$rootScope', function($rootScope) {
$rootScope.$on("$routeChangeSuccess", function(event, next, current) {
$rootScope.showHeader = next.$$route.showHeader;
});
}]);
In your templates, you can just use ng-if="showHeader". It will be easily maintainable I feel.
ng-if="showHeader == true" use like this
<ng-include ng-if="showHeader == true" src="'./partials/mainSubHeader.html'"></ng-include>
Related
AngularJS v1.7.4
I am new to AngularJS and creating a simple app but not sure why one route works (shows the static html from a partial file as well as {{message}} correctly), but the other two routes only show static html and not {{message}} which is being set using $scope.message.
Additionally errors such as
The controller with the name 'ContactController' is not registered.
and
The controller with the name 'AboutController' is not registered.
Are seen in the console when trying to go to 'Contact' and 'About' pages respectively.
For the three routes I have three html files and three controller files. I have made sure to include <body ng-app="gmsApp">.
Files are being loaded as
<script src="./js/bootstrap.bundle.min.js"></script>
<script src="./js/angular.js"></script>
<script src="./js/angular-route.js"></script>
<script src="./js/controllers/about.controller.js"></script>
<script src="./js/controllers/contact.controller.js"></script>
<script src="./js/controllers/home.controller.js"></script>
<link href="./css/bootstrap.min.css" rel="stylesheet" />`
Following advise from other posts I am using the 'regular' js files and not 'minified' versions of angular and angular-route.
The code in main html file is:
var app = angular.module("gmsApp", ['ngRoute', 'gmsApp.controllers']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeController'
}).
when('/about', {
templateUrl: 'partials/about.html',
controller: 'AboutController'
}).
when('/contact', {
templateUrl: 'partials/contact.html',
controller: 'ContactController'
}).
otherwise({
redirectTo: '/home'
});
}]);
/js/controllers/home.controller.js
angular.module('gmsApp.controllers', [])
.controller('HomeController', function ($scope) {
$scope.message = 'Main page of the app';
});
/js/controllers/about.controller.js
angular.module('gmsApp.controllers', [])
.controller('AboutController', function ($scope) {
$scope.message = 'This is about us page';
});
/js/controllers/contact.controller.js
angular.module('gmsApp.controllers', [])
.controller('ContactController', function ($scope) {
$scope.message = 'Contact Us page ...';
});
/partials/home.html
<div ng-controller="HomeController">
<h3>Home page</h3>
<p>{{message}}</p>
</div>
/partials/about.html
<div ng-controller="AboutController">
<h3>About Us</h3>
<p>{{message}}</p>
</div>
/partials/contact.html
<div ng-controller="ContactController">
<h3>Contact Us</h3>
<p>{{message}}</p>
</div>
The error come from the fact that you are recreating your module in each of your controller. This line should be present in only one of your files (could be your main file):
angular.module('gmsApp.controllers', [])
Then in "/js/controllers/home.controller.js,"/js/controllers/about.controller.js" and "/js/controllers/contact.controller.js", you should use it like this:
angular.module('gmsApp.controllers')
Note that this time you don't use the "[]". The difference between the two is that here you will access the already created module.
From angularjs docs:
Beware that using angular.module('myModule', []) will create the
module myModule and overwrite any existing module named myModule. Use
angular.module('myModule') to retrieve an existing module.
I am working on a AngularJs project where I have a Login page and Home page (all other pages will use the same home page view). Now I need to redirect the user from Login page (different layout) to Home page (another different layout).
Right now I have a Index page which contains both ng-app & ng-view tags and my Login page is getting rendered on that but after successful login I don't know how to show my different layout view (Home page).
Also, I have seen many people saying that you can use ng-if to hide/show the required piece (which is placed in same page itself). So, I tried using the rootScope variable to show/hide the span/div before and after login & I worked well. But one thing I noticed in this method is, when I load the login page I was able to see the sidebar, topbar & bottompanel for few seconds but they eventually become invisible and it looks messy.
My app.js:
$stateProvider
.state('login', {
url: "/login",
templateUrl: "/app/views/login/login.html",
controller: "loginController"
})
.state('home', {
url: "/home",
templateUrl: "/app/views/home/home.html",
controller: "homeController"
})
My login page: Very simple page - Contains just two textboxes and a button. When clicking the Login button loginController's login method will be called.
My home page: Very complex page - Contains a side panel, top panel, center panel (where all other views will be displayed) and bottom panel.
I have tried ng-if in the index page to show/hide login and home page using a rootScope variable (called isLoginSuccessful)
My Index page:
<html data-ng-app="myApp">
<body>
<div class="sidebar" id="sidebar" ng-if="isLoginSuccessful">
</div>
<div class="topbar" id="topbar" ng-if="isLoginSuccessful">
</div>
<div class="contentpanel" id="contentpanel">
<div ng-view>
<!-- view goes here-->
</div>
</div>
<div class="bottompanel" id="bottompanel" ng-if="isLoginSuccessful">
</div>
</body>
</html>
My loginController.js:
myApp.controller('loginController', ["$scope", "$rootScope", "$location", function ($scope, $rootScope, $location) {
$rootScope.loggedIn = false;
$scope.login = function () {
//do user validation check here
$rootScope.loggedIn = true;
$location.path("/home"); //redirect to home page
}
}]);
Is there any better way to handle this. Please help me.
Thanks in advance.
You asked how you navigate from the login page to the home page once you have logged in? Your logic is nearly there in the controller, and you have the states already set up, so alter it like so:
myApp.controller('loginController', ["$scope", "$rootScope", "$state", function ($scope, $rootScope, $state) {
$rootScope.loggedIn = false;
$scope.login = function () {
//do user validation check here
$rootScope.loggedIn = true;
$state.go('home'); //redirect to home page
}
}]);
Since the templates contain everything you need, you can get rid of the ng-if attributes since the only way they can navigate to the home page is via the login (and via the $state.go())
The best approach is to use Angular UI router. Take a look here https://angular-ui.github.io/ui-router/
EDIT:
It should work:
app.js
$stateProvider
.state('login', {
url: "/login",
views: {
"content#": {
templateUrl: "/app/views/login/login.html",
controller: "loginController"
}
}
})
.state('home', {
url: "/home",
views: {
"sidebar#": {
templateUrl: "/app/views/home/sidebar.html",
controller: "sidebarController"
},
"topbar#": {
templateUrl: "/app/views/home/topbar.html",
controller: "topbarController"
},
"content#": {
templateUrl: "/app/views/home/home.html",
controller: "homeController"
}
"bottompanel#": {
templateUrl: "/app/views/home/bottompanel.html",
controller: "bottompanelController"
}
}
})
index.html
<html data-ng-app="myApp">
<body>
<div class="contentpanel" id="contentpanel">
<div ui-view="sidebar"></div>
<div ui-view="topbar"></div>
<div ui-view="content"></div>
<div ui-view="bottompanel"></div>
</div>
</body>
</html>
loginController.js
myApp.controller('loginController', ["$scope", "$rootScope", "$state",
function ($scope, $rootScope, $state) {
$rootScope.loggedIn = false;
$scope.login = function () {
//do user validation check here
$rootScope.loggedIn = true;
$state.go("home"); //redirect to home page
}
}]);
I am using templateUrl to display specific php pages in my webpage. Now I wish to scrap the individual php pages and display code with variables passed to it. What is the easiest way to get back to this?
var AppModule = angular.module('App', ['ngAnimate', 'ngRoute']);
AppModule.config(function($routeProvider) {
$routeProvider
.when('/page:pageNumber', {
templateUrl: function ($routeParams) {
return '/app/..../assets/html/page' + $routeParams.pageNumber + '.php';
},
controller: "PageCtrl"
})
.otherwise({
redirectTo: "/page1"
});
});
AppModule.controller("ViewCtrl", function($scope, $timeout) {
$scope.$on("$routeChangeSuccess", function(event, current, previous) {
...stuff...
});
});
Use scripts via text/ng-template, which allows you to write your templates inline while declaring a url to access them by. The following code can go directly in your index.html, and if your config is set to show '/my-template.html', the inline template will be output right in the ng-view above it.
<ng-view />
<script type="text/ng-template" id="/my-template.html">
template goes here
</script>
Then in your config:
.when('/', {
templateUrl: '/my-template.html'
});
Here's a little more info from the Angular docs:
https://docs.angularjs.org/api/ng/directive/script
And lastly, this technique is demonstrated in one of the TodoMVC examples for Angular:
View: https://github.com/tastejs/todomvc/blob/gh-pages/examples/angularjs/index.html
Config: https://github.com/tastejs/todomvc/blob/gh-pages/examples/angularjs/js/app.js
I am a newbie, trying to understand routing, I read the documentation and i injected ngRoute module, but still when i am trying to click on Employee Name its not showing any thing, i have wasted lot of time on this, but no luck. Can some one help.
No errors in the console.
Code:
Plunker
app.js
var app = angular.module('demoApp', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/employeedetail/:empid',
{
controller: 'empDetailController',
templateUrl: '/employeedetail.html'
})
.otherwise({ redirectTo: '/index.html' });
});
The $routeProvider have to be used in conjection with the ng-view directive.
In index.html, replace the employee list template with ng-view, and also remove the controller like this:
<body>
<h2>AngularJS Demo</h2>
<div ng-view></div>
</body>
Put the employee list template as a separate html file e.g. employeelist.html.
Then config the $routeProvider to render the employee list template and its controller by default:
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'employeeController',
templateUrl: 'employeelist.html'
})
.when('/employeedetail/:empid', {
controller: 'empDetailController',
templateUrl: 'employeedetail.html'
})
.otherwise({
redirectTo: '/'
});
})
Example Plunker: http://plnkr.co/edit/mQIaJqZeOal77Z2RxG8z?p=preview
I think your problem come from the fact you don't use :
the ng-view attribute
I am trying to make a very simple app with routes and views, that displays a test text changing into "click" when a button is clicked.
I have an index.html file with an ng-view thats calls properly a test.html view. This view is supposed to use a testCtrl.js with a simple model.
But when it loads, the view seems to be called, but there is a problem with the scope, or the controller. When I click on a button the word test is supposed to become "click" but nothing happens.
here is the index.html
<body ng-app="simtoolbelt">
<div ng-view></div>
<script src="js/modules/angular-route.min.js"></script>
<script src="js/controllers/testCtrl.js"></script>
<script src="js/vendor/jquery.js"></script>
<script src="js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
here is the app.js handling the routes and views:
var simtoolbelt = angular.module('simtoolbelt', ['ngRoute']);
simtoolbelt.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/test', {
templateUrl: 'views/test.html',
controller: 'testCtrl'
}).
otherwise({
redirectTo: '/test'
});
}]);
The test controller:
simtoolbelt.controller('testCtrl', ['$scope', function($scope){
$scope.test = "test";
$scope.change = function($scope){
$scope.test = "Click";
};
}]);
And finally the test view:
<div ng-controller="testCtrl">
<h1 ng-model="test">Le {{test}} fonctionne</h1>
<button ng-click="change()">Click</button>
</div>
All of that is in a localhost, and I really have no clue of what it is I am mising... Thanks lot guys for any help you can give me !
Your function "change" takes the argument "$scope". In ng-click you call a method without arguments.
Remove the parameter from your change method:
$scope.change = function(){
$scope.test = "Click";
};
Furthermore, there is no need for the ng-model attribute in your h1 tag.
Try to change controller definition in your routing to "only controller name" like
simtoolbelt.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/test', {
templateUrl: 'views/test.html',
controller: 'testCtrl'
}).
otherwise({
redirectTo: '/test'
});
}]);
I have not test it yet but it should work.