Angular 1: Change title depending on current route - javascript

How do I change title that is displayed outside of a controller scope depending on current controller provided by router? Basically, I have mainMenu controller that is loaded when specific route is called. However, outside of the view, there is partial included which is a header. I want to change output inside of a header depending on the current route. I added code structure below:
index.html
<div ng-include="'partials/header.html'"></div>
<div ng-view></div>
/partials/header.html
<header ng-controller="HeaderCtrl">
<h1>{{ currentTitle }}</h1>
</header>
/partials/main-menu.html
<div ng-controller="MainMenuCtrl">
</div>
Router
var TaskApp = angular.module('TaskApp', [
'ngRoute',
'taskAppControllers'
]);
TaskApp.config(['$routeProvider',
function($routeProvider){
$routeProvider.
when('/main-menu', {
templateUrl: "partials/main-menu.html",
controller: "MainMenuCtrl"
}).
otherwise({
redirectTo: "/"
});
}]);
Controllers:
var taskAppControllers = angular.module('taskAppControllers',[]);
taskAppControllers.controller('TaskAppCtrl',[function(){}]);
taskAppControllers.controller('DesktopCtrl',[function(){}]);
taskAppControllers.controller('MainMenuCtrl', ['$scope','$http',
function($scope, $http){
$http.get('data/main-menu.json?' + Math.random()).success(function(data){
$scope.mainMenuOptions = data;
});
$scope.currentTitle = "Main menu"
}]);
taskAppControllers.controller('HeaderCtrl', ['$scope',
function($scope){
//
}]);

You could add one more property with each route options, which will something like title
when('/main-menu', {
templateUrl: "partials/main-menu.html",
controller: "MainMenuCtrl",
title: 'Main Page'
}).
Then place $routeChangeSuccess(it gets fired when route changes are succeeded) event inside HeaderCtrl, and then do grab current route object and get title from it and set it to currentTitle scope variable
$scope.$on('$routeChangeSuccess', function(event, current) {
$scope.currentTitle = current.title;
});

Related

Pulling list item data through to a new view created by the scope data

Although there are a few of these questions rocking about, none of them seem to have a good working example and i cant seem to figure out how to apply it to my project.
What i want to do is pull the data through from the list item into another view to use as a profile page.
JS
var app = angular.module('passDataDemo', ['ngRoute']);
// Configure our routes
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
// Route for the global controller
.when('/', {
templateUrl: 'list.html'
})
// Route for profile
.when('/:item.firstname', {
templateUrl: 'listItemProfile.html'
})
// Fallback
.otherwise({
redirectTo: '/'
});
}]);
// Main controller
app.controller('mainCtrl', ['$scope', '$http', function($scope, $http) {
$http.get('items.json').success(function(data) {
$scope.items = data;
});
}]);
View 1 html
<ul ng-repeat="item in items">
<li>
<p>{{item.firstname}}</p>
<p>{{item.surname}}</p>
<button ng-click="viewTheProfileView()">View Profile</button>
View 2 html
<h1>ITEM PROFILE</h1>
<p>{{item.firstname}}</p>
<p>{{item.surname}}</p>
Here is my Plunker - https://plnkr.co/edit/gZj5gOZEcCOLNbdxwduw?p=preview
After looking at your plunker, I see that you are only using one controller for all of your views. Because of this, you would only need to set the value of $scope.item and it will show up in your listItemProfile.html. Therefore, I would change your button to pass in the current item to the controller: <button ng-click="viewTheProfileView(item)">View Profile</button>.
Then in your controller:
$scope.viewTheProfileView = function(item) {
$scope.item = item;
};
This will allow clicking the ITEM PROFILE button in index.html to display the correct information.

ui-router nested view doesn't get loaded properly

Hey I have a simple app which I have created.
The app has the following views
1.Settings - Main View.
2.Profile - Sub view, child of Settings View.
3.Account - Sub View, child of Settings View.
I want the application to start from profile page, therefore I wrote the following code:
$urlRouterProvider.otherwise('/profile');
But apparently noting is happen, I got a blank screen and can't see the view properly(settings.profile).
I have added my code to a plunker to make things more convenient and accessible for other developers which can help me solve my problem.
https://plnkr.co/edit/RFP5dUNV876cy8vRDuvL?p=preview
Main main code is like this:
/**
* Module
*
* Description
*/
var app = angular.module('app', ['ui.router'])
app.controller('mainCtrl', ['$scope', function($scope){
$scope.title="Index Page";
}]);
app.controller('ProfileController', ['$scope', function($scope){
$scope.title="Profile Page";
}]);
app.controller('AccountController', ['$scope', function($scope){
$scope.title="Account Page";
}]);
app.controller('SettingsController', ['$scope', function($scope){
$scope.title="Settings Page";
}]);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('settings', {
url: '/settings',
templateUrl: 'settings.html',
controller: 'SettingsController'
})
.state('settings.profile', {
url: '/profile',
templateUrl: 'profile.html',
controller: 'ProfileController'
})
.state('settings.account', {
url: '/account',
templateUrl: 'account.html',
controller: 'AccountController'
});
$urlRouterProvider.otherwise('/profile');
});
Change the .otherwise function to:
$urlRouterProvider.otherwise('/settings/profile');
Since the other routes are nested within settings state, you can only access the nested views via the <ui-view> in settings.html. The urls are also nested within each other if url parameter is defined in both, so /settings/profile is required.
Updated Plnkr

Using ngroute to redirect unauthorized users in Angular

I am making a web app using Angular for front-end.
If user whose role is teacher trying to access applicant's portal, I want to block them by showing 404.html template. I do not want to redirect the users to www.example.com/404 but rather just let them stay at where they are at www.example.com/teacher but render 404.html template.
I am not sure how I can achieve this using ngroute. Here is the code what I have in app.js:
app.config(['$routeProvider', '$locationProvider', 'CookieProvider',
function ($routeProvider, $locationProvider, CookieProvider) {
var cookieData = CookieProvider.$get().getCookieData();
$routeProvider.when('/applicant', {
templateUrl: '/front-end/public/views/Prescreening/review.html',
controller: 'ReviewCtrl',
resolve:{
"check":function($location, CookieService) {
var cookieData = CookieService.get();
if(cookieData["user_role"] == 'teacher'){
$location.path('/404')
}
}
}
}).when('/404', {
templateUrl: '/404.html'
}).otherwise({
templateUrl: '/404.html'
});
}]);
How can I render 404.thml without redirecting the user to /404 ?
Let's say you have a state like this.
.state('dashboard.users', {
url: '/users/:isAdmin',
templateUrl: 'modules/dashboard/templates/users.html',
controller: 'usersController',
})
Try this.
angular.module(...)
.config( ['$routeProvider', function($routeProvider) {...}] )
.run(function($rootScope, $location) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
// You can pass the user role to the params
// of the state and you will see that on the
// toParams call callback ex. {isAdmin:false}
if(!toParams.isAmin){
toState.templateUrl = "modules/404/templates/404.html";
}
});
})
})
UPDATE
The callback toState actually contains the following
url = url of the current state ex. /user
templateUrl = path to the template ex. path/to/something.html
controller = the controller name of the state ex. usersController
name = the state name ex. dashboard.user
When this line gets executed toState.templateUrl = "modules/404/templates/404.html"; The current template of your state which falls under the <div ui-view></div> will have the 404.html that you desire.
IMPORTANT
You must use ui.router and not ngRouter to make this implementation work.
After some efforts I got it working... Here are the different codes...
I have used bower so please replace with your paths..
Here is the plunk.. I got it working..
https://plnkr.co/edit/dK7n6PmhldJ1p0plWPp2?p=preview
index.js
var app = angular.module('myApp',['ngRoute']);
app.config(['$routeProvider',function ($routeProvider) {
$routeProvider
.when('/applicant', {
template: 'Applicant!',
controller: function($scope){
alert("Applicant Controller");
}
})
.when('/404', {
templateUrl: '404'
})
.otherwise({
templateUrl : '404.html'
});
}]);
index.html
<html>
<head>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src = "index.js"></script>
</head>
<body ng-app="myApp">
<ng-view></ng-view>
</body>
</html>
404.html
<h1>404 page</h1>

How to set ng-show on a specific element through different views/controllers?

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

AngularJS routing is not working: no events on link clicks, no $routeParams

Somehow my app stopped working during development and I really cannot get what's wrong with it.
I've removed everything, the only code remaining is:
function handlerControl($scope, $routeParams, $location){
$scope.route = $routeParams;
}
var app = angular.module('Hello', []).config(
function($routeProvider){
$routeProvider.when('/:a/:b', {controller: handlerControl});
}
);
and html is
<body ng-app="Hello">
<div ng-controller="handlerControl">
{{route}}
</div>
</body>
omitting head part with including everything.
When I go to
http://helloday/#/a/b/
I'm getting an empty hash while expecting to get {a: 'a', b: 'b'}
What I'm doing wrong?
Bit modified(to make it work) jsFiddle: http://jsfiddle.net/wWDj2/http://jsfiddle.net/wWDj2/
Routing requires you use ngView, and that you specify either a template or a templateUrl:
App code.
var app = angular.module('myApp', []);
app.config(function($routeProvider) {
$routeProvider.when('/foo/:id', {
controller: 'FooCtrl',
template: '<h1>Foo {{id}}</h1>'
})
.when('/bar/:test', {
controller: 'BarCtrl',
templateUrl: 'bartemplate.html'
})
.otherwise({
controller: 'DefaultCtrl',
template: '<h1>This is the default</h1>'
});
});
app.controller('FooCtrl', function($scope, $routeParams) {
$scope.id = $routeParams.id;
});
app.controller('BarCtrl', function($scope, $routeParams) {
$scope.test = $routeParams.test;
});
app.controller('DefaultCtrl', function($scope){});
Your main page's markup:
<div ng-app="myApp">
Foo 123
Bar Blah
Default route
<hr/>
<div ng-view>
<!-- your processed view will show up here -->
</div>
</div>

Categories