I want to pass a custom object to another state via $state.go() in UI-Router.
var obj = {
a: 1,
b: 2,
fun: function() {
console.log('fun');
}
}
$state.go('users', obj);
But I need to run fun() in target state, so I can't pass this object in URL parameter. In target controller, I tried to fetch the value of obj via $stateParams but got empty object {}:
function UserCtrl($stateParams) {
console.log($stateParams); // will be empty
}
So how to pass obj to state "users" correctly?
Define state with parameters like this:
$stateProvider
.state('user', {
url: '/user',
params: {
obj: null
},
templateUrl: 'templates/user.html',
controller: 'UserCont'
})
when calling pass parameter like this:
$state.go('user',{obj: myobj});
in the controller UserCon receive parameter like:
$state.params.obj
User $state is one of the parameter in the controller defined like
function UserCon($scope, $http, $state){
var obj = {
a: 1,
b: 2,
fun: function() {
console.log('fun');
}
}
$state.go('users', obj);
.....
$stateProvider
.state('user', {
url: '/user/:obj',
templateUrl: 'templates/user.html',
controller: 'UserCont'
})
..... or .....
$stateProvider
.state('user', {
url: '/user',
params: {
obj: null
},
templateUrl: 'templates/user.html',
controller: 'UserCont'
})
.....
function UserCtrl($state) {
console.log($state.params.obj);
}
//Use the method chaining mechnism as show below:
var RoutingApp = angular.module('RoutingApp', ['ui.router']);
RoutingApp.config( [ '$stateProvider', '$urlRouterProvider','$locationProvider', function( $stateProvider, $urlRouterProvider,$locationProvider ){
$stateProvider
.state('home', {
url:'/home',
templateUrl: 'template/home.html',
controller: 'homeController as homeCtrl',
data: {
customDatahome1:"Home Custom Data 1",
customDatahome2:"Home Custom Data 2"
}
})
.state('courses', {
url:'/courses',
templateUrl: 'template/courses.html',
controller: 'coursesController as coursesCtrl',
data: {
customDatacourses1:"Courses Custom Data 1",
customDatacourses2:"Courses Custom Data 2"
}
})
.state('students', {
url:'/students',
templateUrl: 'template/students.html',
controller: 'studentsController'
})
.state('studentDetails', {
url:'/students/:id',
templateUrl: 'template/studentDetails.html',
controller: 'studentDetailsController'
});
$urlRouterProvider.otherwise('/home');
$locationProvider.html5Mode(true);
} ] );
RoutingApp.controller( 'homeController', function( $state ){
var vm = this;
vm.message = "Home Page";
this.customDatahome1 = $state.current.data.customDatahome1;
this.customDatahome2 = $state.current.data.customDatahome2;
this.customDatacourses1 = $state.get('courses').data.customDatacourses1;
this.customDatacourses2 = $state.get('courses').data.customDatacourses2;
});
RoutingApp.controller('coursesController', function($scope){
var vm = this;
$scope.courses = ['PHP','AngularJS','Hadoop','Java','.Net','C#'];
console.log("Hello Courses");
});
Template:home.html
<h1 ng-controller="homeController as homeCtrl">{{homeCtrl.message}} <br> {{homeCtrl.message1}}</h1>
<div>
Vision Academy is established in 2011 By 2 Software Engineer offer very cost effective training.
</div>
<ul>
<li>Training Delivered by real time software experts having more than 10 years of experience </li>
<li>Realtime Project discussion relating to the possible interview questions</li>
<li>Trainees can attend training and use lab untill you get job</li>
<li>Resume prepration and mock up interview</li>
<li>100% placement asistance</li>
<li>Lab facility</li>
</ul>
<fieldset ng-controller="homeController as homeCtrl">
<legend>Home</legend>
Custom Data Home 1 : {{homeCtrl.customDatahome1}}<br>
Custom Data Home 2 : {{homeCtrl.customDatahome2}}<br>
</fieldset>
<fieldset ng-controller="homeController as homeCtrl">
<legend>Courses</legend>
Custom Data Courses 1 : {{homeCtrl.customDatacourses1}}<br>
Custom Data Courses 2 : {{homeCtrl.customDatacourses2}}<br>
</fieldset>
Related
I'm new to AngularJS and I'm developing a small contacts app using AngularJS and Material Design.
I'd like to pass an object (using ng-click) containing several fields to a different state using $state.go.
My HTML looks like this:
<md-list-item class="md-2-line" ng-repeat="c in contacts" >
<img src="../img/user.svg" class="md-avatar"/>
<div class="md-list-item-text" ng-click="goToContactInfo(c)" >
My JS code:
app.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
// configure "contacts" page
.state('contacts', {
url: "/contacts",
templateUrl: "contacts.html",
controller: function ($scope, $state) {
$scope.contacts = [
{ name: "aaa", phone: "555555" },
{ name : "bbb" , phone: "666666"}
];
$scope.goToContactInfo = function (contact) {
$state.go("contactInfo", contact);
};
}
})
// configure "contactInfo" page
.state('contactInfo', {
url: "/contactInfo",
templateUrl: "contactInfo.html",
controller: function ($scope, $stateParams) {
var contactInfo = $stateParams.contact;
$scope.name = contactInfo.name;
$scope.phone = contactInfo.phone;
}
})
I expect var contactInfo to be an object containing name and phone but I'm getting an undefined instead.
Your controller should be,
controller: function ($scope, $state) {
var contactInfo = $state.params.contact;
}
EDIT
First of all you cannot pass an Object to another state like this, and there are few mistkaes in your configuration.
You need to define your router config with the parameter. Also consider using an id to pass to another state and retrieve the details using an API call or use localstorage.
Here is the fix, i have considered phone number as the state param here,
.state('contactInfo', {
url: "contactInfo/:phone",
templateUrl: "contactInfo.html",
controller: function ($scope, $state, $stateParams) {
console.log('state2 params:', $stateParams);
var contactInfo = $stateParams.phone;
console.log(contactInfo);
alert(JSON.stringify(contactInfo));
$scope.name = contactInfo.name;
$scope.phone = contactInfo.phone;
}
})
and you need to pass the info as,
$state.go("contactInfo", { phone : contact.phone });
PLUNKER DEMO
$scope.goToContactInfo = function (contact) {
$state.go("contactInfo", {contact}); <-- this
};
.state('contactInfo', {
url: "/contactInfo",
templateUrl: "contactInfo.html",
params:{ <-- this
contact: null
},
controller: function ($scope, $state) {
var contactInfo = $state.params.contact;
alert(contactInfo);
$scope.name = contactInfo.name;
$scope.phone = contactInfo.phone;
}
})
I'm using AngularJS's UI-Router to manage routes for my web application.
I have two states: parent_state and child_state arranged as shown below.
$stateProvider
.state('parent_state', {
abstract: true,
views: {
'#' : {
templateUrl: 'http://example.com/parent.html',
controller: 'ParentCtrl'
}
}
})
.state('child_state', {
parent: 'parent_state',
url: '/child',
params: {
myArg: {value: null}
},
views: {
'mainarea#parent_state': {
templateUrl: 'http://example.com/child.html',
controller: 'ChildCtrl'
}
}
})
From within ChildCtrl, I can access myArg like this:
app.controller("ChildCtrl", function($stateParams) {
console.log('myArg = ', $stateParams.myArg);
});
Is it possible for me to access myArg and have it displayed in the html page parent.html? If so, how can it be done? I see that the ParentCtrl controller for the abstract state is never even called.
This question addresses a related topic. But it doesn't show me how to display a parameter to the child state in a template of the parent state.
The first thing that comes to my mind is to use events for notifying parent after child param change. See the following (you can even run it here).
Child, after rendering, emits an event to the parent with the changed value of the parameter. Parent grabs and displays it in its own template.
angular.module('myApp', ['ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('parent_state', {
abstract: true,
template: "<h1>Parent! Value from child: {{ paramFromChild }}</h1><div ui-view></div>",
controller: function ($scope) {
$scope.$on('childLoaded', function (e, param) {
$scope.paramFromChild = param;
});
}
})
.state('child_state', {
parent: 'parent_state',
url: '/child',
params: {
myArg: {value: null}
},
template: '<h2>Child! Value: {{ param }}</h2>',
controller: function($stateParams, $scope){
$scope.param = $stateParams.myArg;
$scope.$emit('childLoaded', $stateParams.myArg);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.20/angular-ui-router.js"></script>
<div ng-app="myApp">
<a ui-sref="child_state({myArg: 'first'})">First link</a>
<a ui-sref="child_state({myArg: 'second'})">First second</a>
<div ui-view></div>
</div>
Is it possible for me to access myArg and have it displayed in the
html page parent.html?
That is against the principle of the UI-Router. Parent params can be consumed in children, but not vice versa. How would parent view know about changes WITHOUT re-initializing the controller? You need something like watching.
The true way is to employ Multiple Named Views. Look at this working plunkr.
Yes, this is possible.
Using $stateChangeSuccess:
You can use $stateChangeSuccess to achieve this.
For example:
.state('main.parent', {
url: '/parent',
controller: 'ParentController',
controllerAs: 'vm',
templateUrl: 'app/parent.html',
data: {
title: 'Parent'
}
})
.state('main.parent.child', {
url: '/child',
controller: 'ChildController',
controllerAs: 'vm',
templateUrl: 'app/child.html'
})
And in the runblock call it as follows:
$rootScope.$on('$stateChangeSuccess', function (event, toState, fromState) {
var current = $state.$current;
if (current.data.hasOwnProperty('title')) {
$rootScope.title = current.data.title;
} else if(current.parent && current.parent.data.hasOwnProperty('title')) {
$rootScope.title = current.parent.data.title;
} else {
$rootScope.title = null;
}
});
Then you can access the $rootScope.title from the child controller since it is globally available.
Using a Factory or Service:
By writing setters and getters you can pass data between controllers. So, you can set the data from the child controller and get the data from the parent controller.
'use strict';
(function () {
var storeService = function () {
//Getters and Setters to keep the values in session
var headInfo = [];
return {
setData: function (key, data) {
headInfo[key] = data;
},
getData: function (key) {
return headInfo[key];
}
};
};
angular.module('MyApp')
.factory('StoreService', storeService);
})(angular);
Set data from child controller
StoreService.setData('title', $scope.title)
Get data
StoreService.getData('title');
Using events $emit, $on:
You can emit the scope value from the child controller and listen for it in the parent scope.
I am using UI Router and UI Bootstrap in my Angular app. I'd like to use a service so that I can display alert messages from various controllers. I want the alert to display at the top of the screen. Any suggestions on how to modify the code below so that the alert will display at the top of the page and display messages from different controllers?
I'm using this Stack Overflow post as a model.
HTML:
<alert ng-repeat="alert in allInfos()" type="{{alert.type}}" close="closeAlert($index)"
ng-cloak>{{alert.msg}}</alert>
Service:
.factory('Informer', function(){
var messages = [];
var Informer = {};
Informer.inform = function(msg, type) {
messages.push({
msg: msg,
type: type
});
};
Informer.allInfos = function() {
return messages;
};
Informer.remove = function(info) {
messages.splice(messages.indexOf(info), 1);
};
return Informer;
})
Controller:
.controller('PaymentFormCtrl',
function ($scope, $http, Informer) {
$scope.handleStripe = function () {
Informer.inform("There was a problem authorizing your card.", "danger");
$scope.messages = 'problem';
$scope.allInfos = Informer.allInfos;
$scope.remove = Informer.remove;
}
};
});
.controller('ContactFormCtrl',
function ($scope, $http, Informer) {
//. . .
Informer.inform("There is already an account with that email address", "danger");
$scope.messages = 'problem';
$scope.allInfos = Informer.allInfos;
$scope.remove = Informer.remove;
}
};
});
Routers:
.state('home', {
url: '/',
views: {
'top': {
templateUrl: 'views/bigHero.html'
},
'bottom': {
templateUrl: 'views/home.html',
controller: 'HomeCtrl'
}
}
})
.state('payment', {
url: '/payment',
views: {
'top': {
templateUrl: 'views/customerinfo.html',
controller: 'ContactFormCtrl'
},
'bottom': {
templateUrl: 'views/creditcard.html',
controller: 'PaymentFormCtrl'
},
}
});
});
You really have three good options that I can think of off the top of my head.
Create a global or what i like to call a "RootController" of your application bound higher up in your DOM so that the other controllers scope naturally extends it. i.e.:
<div ng-controller="RootController">
<div ui-view></div>
</div>
You can create a parent state with UI Router that both your child states inherit, giving a similar effect to the case above:
$stateProvider.state('parent', {controller: 'ParentController'});
$stateProvider.state('parent.child1', {controller: 'Child1Controller'});
$stateProvider.state('parent.child2', {controller: 'Child2Controller'});
You can pass all shared functionality through a service, which acts as an error message to your necessary controllers.
myService.service('errorService', function() {
this.errorMessage = 'Everything is happy!';
});
myService.controller('PaymentFormCtrl', function($scope, errorService) {
$scope.errorService = errorService;
$scope.setError = function() {
errorService.errorMessage = 'An error happened!';
};
});
This works, but Json is not how I want to retrieve the data:
var states = [
{ name: 'main', url: '/', templateUrl: '/views/main.html', controller: 'MainCtrl' },
{ name: 'login', url: '', templateUrl: '/views/login-form.html', controller: 'LoginCtrl' },
{ name: 'logout', url: '', templateUrl: '', controller: 'LogoutCtrl' },
{
name: 'sales',
url: '',
templateUrl: '/views/sales-data.html',
controller: 'SalesDataCtrl',
resolve: {
user: 'User',
authenticationRequired:
['user', function(user) { user.isAuthenticated(); }]
}
}
];
angular.forEach(states, function (state) {
$stateProvider.state(state.name, state);
});
This does not work in retrieving the data:
app.config(['$locationProvider', '$resourceProvider', '$stateProvider', function ($locationProvider, $resourceProvider, $stateProvider) {
$locationProvider.html5Mode(true);
not working ---> var states = $resource('http://localhost:9669/api/breeze/states').query();
angular.forEach(states, function(state) {
$stateProvider.state(state.name, state);
});
}]);
My question is two-fold:
How does one retrieve remote data inside app.config so as to populate $StateProvider.
I know even when that is acheived, I will have a problem with the return value of
"['user', function(user) { user.isAuthenticated(); }]"
as it will come back as a string and angular will not recognize it as a function.
How can I overcome that issue?
[Side note: the api call does work, the issue is not the api controller.]
Thank you.
[Solution]
Documentation is piece-meal on this matter, but after sewing various posts together I found the answer.
First one must understand that data cannot be populated in the $stateProvider as it is part of app.config because app.config only initializes providers, the actual http service has to be performed in app.run.
Step 1: Declare 2 Globals, ie. $stateProviderRef and $urlRouterProviderRef references before the app.module and pass the actual $stateProvider & $urlRouterProvider references to them in app.config:
(function() {
var id = 'app';
var $stateProviderRef = null;
var $urlRouterProviderRef = null;
......
// Create the module and define its dependencies.
app.config(function($stateProvider, $urlRouterProvider) {
$stateProviderRef = $stateProvider;
$urlRouterProviderRef = $urlRouterProvider;
});
.......
Step 2: Create a Custom Factory Provider:
app.factory('menuItems', function($http) {
return {
all: function() {
return $http({
url: 'http://localhost:XXXX/api/menuitems',
method: 'GET'
});
}
};
});
Step 3: Call the custom provider in app.run:
app.run(['$q', '$rootScope', '$state','$urlRouter', 'menuItems',
function($q, $rootScope, $state, $urlRouter, menuItems) {
breeze.core.extendQ($rootScope, $q);
menuItems.all().success(function (data) {
angular.forEach(data, function (value, key) {
var stateName = 'state_' + value.OrderNum; //<-- custom to me as I have over 300 menu items and did not want to create a stateName field
$stateProviderRef.state(stateName, {url:value.url, templateUrl:value.templateUrl, controller:value.controller });
});
// because $stateProvider does not have a default otherwise
$urlRouterProviderRef.otherwise('/');
});
.....
}
]);
I am migrating my AngularJS based app to use ui-router instead of the built in routing. I have it configured as shown below
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl : 'views/home.html',
data : { pageTitle: 'Home' }
})
.state('about', {
url: '/about',
templateUrl : 'views/about.html',
data : { pageTitle: 'About' }
})
});
How can I use the pageTitle variable to dynamically set the title of the page? Using the built in routing, I could do
$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){
$rootScope.pageTitle = $route.current.data.pageTitle;
});
and then bind the variable in HTML as shown below
<title ng-bind="$root.pageTitle"></title>
Is there a similar event that I can hook into using ui-router? I noticed that there are 'onEnter' and 'onExit' functions but they seem to be tied to each state and will require me to repeat code to set the $rootScope variable for each state.
Use $stateChangeSuccess.
You can put it in a directive:
app.directive('updateTitle', ['$rootScope', '$timeout',
function($rootScope, $timeout) {
return {
link: function(scope, element) {
var listener = function(event, toState) {
var title = 'Default Title';
if (toState.data && toState.data.pageTitle) title = toState.data.pageTitle;
$timeout(function() {
element.text(title);
}, 0, false);
};
$rootScope.$on('$stateChangeSuccess', listener);
}
};
}
]);
And:
<title update-title></title>
Demo: http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home
Code: http://plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview
Even with $stateChangeSuccess the $timeout has been needed for the history to be correct, at least when I've tested myself.
Edit: Nov 24, 2014 - Declarative approach:
app.directive('title', ['$rootScope', '$timeout',
function($rootScope, $timeout) {
return {
link: function() {
var listener = function(event, toState) {
$timeout(function() {
$rootScope.title = (toState.data && toState.data.pageTitle)
? toState.data.pageTitle
: 'Default title';
});
};
$rootScope.$on('$stateChangeSuccess', listener);
}
};
}
]);
And:
<title>{{title}}</title>
Demo: http://run.plnkr.co/d4s3qBikieq8egX7/#/credits
Code: http://plnkr.co/edit/NpzQsxYGofswWQUBGthR?p=preview
There is a another way of doing this by combining most of the answers here already. I know this is already answered but I wanted to show the way I dynamically change page titles with ui-router.
If you take a look at ui-router sample app, they use the Angular .run block to add the $state variable to $rootScope.
// It's very handy to add references to $state and $stateParams to the $rootScope
// so that you can access them from any scope within your applications.
// For example, <li ng-class="{ active: $state.includes('contacts.list') }">
// will set the <li> to active whenever 'contacts.list' or one of its
// decendents is active.
.run([ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
With this defined, you can then easily dynamically update your page title with what you have posted but modified to use the defined state:
Setup the state the same way:
.state('home', {
url: '/home',
templateUrl : 'views/home.html',
data : { pageTitle: 'Home' }
})
But edit the html a bit...
<title ng-bind="$state.current.data.pageTitle"></title>
I can't say this is any better than the answers before, but it was easier for me to understand and implement.
The angular-ui-router-title plugin makes it easy to update the page title to a static or dynamic value based on the current state. It correctly works with browser history, too.
$stateChangeSuccess is now deprecated in UI-Router 1.x and disabled by default. You'll now need to use the new $transition service.
A solution isn't too difficult once you understand how $transition works. I got some help from #troig in understanding it all. Here's what I came up with for updating the title.
Put this in your Angular 1.6 application. Note that I'm using ECMAScript 6 syntax; if you are not, you'll need e.g. to change let to var.
.run(function($transitions, $window) {
$transitions.onSuccess({}, (transition) => {
let title = transition.to().title;
if (title) {
if (title instanceof Function) {
title = title.call(transition.to(), transition.params());
}
$window.document.title = title;
}
});
Then just add a title string to your state:
$stateProvider.state({
name: "foo",
url: "/foo",
template: "<foo-widget layout='row'/>",
title: "Foo Page""
});
That will make the words "Foo Page" show up in the title. (If a state has no title, the page title will not be updated. It would be a simple thing to update the code above to provide a default title if a state does not indicate one.)
The code also allows you to use a function for title. The this used to call the function will be the state itself, and the one argument will be the state parameters, like this example:
$stateProvider.state({
name: "bar",
url: "/bar/{code}",
template: "<bar-widget code='{{code}}' layout='row'/>",
title: function(params) {
return `Bar Code ${params.code}`;
}
});
For the URL path /bar/code/123 that would show "Bar Code 123" as the page title. Note that I'm using ECMAScript 6 syntax to format the string and extract params.code.
It would be nice if someone who had the time would put something like this into a directive and publish it for everyone to use.
Attaching $state to $rootscope to use anywhere in the app.
app.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
// It's very handy to add references to $state and $stateParams to the $rootScope
// so that you can access them from any scope within your applications.For example,
// <li ng-class="{ active: $state.includes('contacts.list') }"> will set the <li>
// to active whenever 'contacts.list' or one of its decendents is active.
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]
)
<title ng-bind="$state.current.name + ' - ui-router'">about - ui-router</title>
I found this way really easy:
.state('app.staff.client', {
url: '/client/mine',
title: 'My Clients'})
and then in my HTML like this:
<h3>{{ $state.current.title }}</h3>
Just update window.document.title:
.state('login', {
url: '/login',
templateUrl: "/Login",
controller: "loginCtrl",
onEnter: function($window){$window.document.title = "App Login"; }
})
That way 'ng-app' does not need to move up to the HTML tag and can stay on the body or lower.
I'm using ngMeta, which works well for not only setting page title but descriptions as well. It lets you set a specific title/description for each state, defaults for when a title/description is not specified, as well as default title suffixes (i.e., ' | MySiteName') and author value.
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/home.html',
controller: 'HomeController',
meta: {
'title': 'Home',
'titleSuffix': ' | MySiteName',
'description': 'This is my home page description lorem ipsum.'
},
})
You are actually really close with your first answer/question. Add your title as a data object:
.state('home', {
url: '/home',
templateUrl : 'views/home.html',
data : { pageTitle: 'Home' }
})
In your index.html bind the data directly to the page title:
<title data-ng-bind="$state.current.data.pageTitle + ' - Optional text'">Failsafe text</title>
I ended up with this combination of Martin's and tasseKATT's answers - simple and without any template related stuff:
$rootScope.$on("$stateChangeSuccess", function (event, toState) {
$timeout(function () { // Needed to ensure the title is changed *after* the url so that history entries are correct.
$window.document.title = toState.name;
});
});
Why not just:
$window.document.title = 'Title';
UPDATE: Full Directive Code
var DIRECTIVE = 'yourPageTitle';
yourPageTitle.$inject = ['$window'];
function yourPageTitle($window: ng.IWindowService): ng.IDirective {
return {
link: (scope, element, attrs) => {
attrs.$observe(DIRECTIVE, (value: string) => {
$window.document.title = value;
});
}
}
}
directive(DIRECTIVE, yourPageTitle);
Then in every page you would just include this directive:
<section
your-page-title="{{'somePage' | translate}}">
If you are using ES6, this works just fine :).
class PageTitle {
constructor($compile, $timeout) {
this.restrict = 'A';
this._$compile = $compile;
this.$timeout = $timeout;
}
compile(element) {
return this.link.bind(this);
}
link(scope, element, attrs, controller) {
let defaultTitle = attrs.pageTitle ? attrs.pageTitle : "My Awesome Sauce Site";
let listener = function(event, toState) {
let title = defaultTitle;
if (toState.data && toState.data.title) title = toState.data.title + ' | ' + title;
$('html head title').text(title);
};
scope.$on('$stateChangeStart', listener);
}
}
export function directiveFactory($compile) {
return new PageTitle($compile);
}
directiveFactory.injections = ['$compile', '$timeout'];
export default PageTitle;
Maybe you can try this directive.
https://github.com/afeiship/angular-dynamic-title
Here is the example:
html:
<title dynamic-title>Title</title>
State1 page
State2 page
javascript:
var TestModule = angular.module('TestApp', ['ui.router','nx.widget'])
.config(function ($stateProvider, $urlRouterProvider) {
//
// For any unmatched url, redirect to /state1
$urlRouterProvider.otherwise("/state1");
//
// Now set up the states
$stateProvider
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html",
data:{
pageTitle:'State1 page title11111'
}
})
.state('state2', {
url: "/state2",
templateUrl: "partials/state2.html",data:{
pageTitle:'State2 page title222222'
}
});
})
.controller('MainCtrl', function ($scope) {
console.log('initial ctrl!');
});
For Updated UI-Router 1.0.0+ versions,
(https://ui-router.github.io/guide/ng1/migrate-to-1_0)
Refer to following code
app.directive('pageTitle', [
'$rootScope',
'$timeout',
'$transitions',
function($rootScope, $timeout,$transitions) {
return {
restrict: 'A',
link: function() {
var listener = function($transitions) {
var default_title = "DEFAULT_TITLE";
$timeout(function() {
$rootScope.page_title = ($transitions.$to().data && $transitions.$to().data.pageTitle)
? default_title + ' - ' + $transitions.$to().data.pageTitle : default_title;
});
};
$transitions.onSuccess({ }, listener);
}
}
}
])
Add following to your index.html:
<title page-title ng-bind="page_title"></title>
if (abp.auth.hasPermission('Center.Category.GroupItem')) {
$stateProvider.state('groupItems', {
title: 'GroupItems',
url: '/groupItems',
templateUrl: '~/App/product/views/center/groupItem/index.cshtml'
controller: 'app.product.views.center.groupItem.index as vm'
});
}
<title>{{$state.current.title ? $state.current.title : 'MiniShop'}}</title>