UI Router dynamic <title> tag - angularjs

I'm adding a title to every state in the ui-router like that:
.state('projects', {
url: '/',
templateUrl: 'projects/projects.html',
ncyBreadcrumb: {
label: 'Projects'
},
data : {title: 'Projects'}
})
And then the title attribute takes that data:
<title ng-bind="$state.current.data.title"></title>
How can I take data from the state parameters and add it to the title in the above example? I tried the following with no luck:
.state('project', {
abstract: true,
url: '/projects/:projId',
resolve:{
projId: ['$stateParams', function($stateParams){
return $stateParams.projId;
}]
},
controller: 'projectCtrl',
templateUrl: 'project/project.html',
ncyBreadcrumb: {
label: 'Project',
parent: 'projects'
},
data : {title: '{{state}}'}
})

you have to use app.run() in your app.js file and assign your title in $rootScope.title . you can follow this code
app.run(function($rootScope){
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState){
$rootScope.title=toState.data.title;
});
});
after this then bind the variable in your html like this
<title ng-bind="title"></title>
I think it will helpful

There is a working example
I would say, you are almost there. The title could look like this:
<title>{{$state.current.data.title}} {{$stateParams.ID}}</title>
Let's have these two states:
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
data : { title: 'Title for PARENT' },
})
.state('parent.child', {
url: "/child/:ID",
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
data : { title: 'Title for CHILD' },
})
;
And call them like this:
<a ui-sref="parent">
<a ui-sref="parent.child({ID:1})">
<a ui-sref="parent.child({ID:2})">
And with this hook:
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
So, the point is, that in a $rootScope we can access both, $state.current and $stateParams
Check it here (NOTE, to see plunker in separated window, click the right -top corner blue icon - new window will change the title as well)

I'd suggest you to use params option instead of using data option, because params can be optional and you can set it dynamically by passing parameter inside your $state.go or ui-sref directive.
Code
.state('projects', {
url: '/',
templateUrl: 'projects/projects.html',
ncyBreadcrumb: {
label: 'Projects'
},
params: {
title: { value: null }
}
});
From Controller
$state.go('projects', {title: 'Page1'}); //you can change title while calling state
From HTML
ui-sref="projects({title: 'Something Else'})"

Related

How to change URL of the page in AngularJS routing in one controller?

this is the routing configuration:
tapp.config(function ($routeProvider) {
$routeProvider.when('/', {
title: 'Home',
controller: 'tCtrlr',
templateUrl: '../HTML/Index.html',
}),
$routeProvider.when('/Tasks', {
title: 'Tasks',
controller: 'tCtrlr',
templateUrl: '../HTML/Tasks.html',
}),
$routeProvider.when('/MyTasks', {
title: 'My Tasks',
controller: 'tCtrlr',
templateUrl: '../HTML/MyTasks.html',
})
When navigating between the pages the title is not set, I've read some SO threads regarding to this issue, but most assume I have a controller for every page. So how could I get the title property in the when function?
The way I do it is quite simple. In route configuration you define title:
.when('/dashboard', {
title : 'My Dashboard',
templateUrl : 'templates/sections/app-dashboard.html',
controller : 'DashboardController'
})
then you listen $routeChangeSuccess event and just set document.title. In application run block (the best place for this).
app.run(['$rootScope', '$route', function($rootScope, $route) {
$rootScope.$on('$routeChangeSuccess', function() {
document.title = $route.current.title;
});
}]);
The benefit of this approach is that it allows you to avoid one more binding ng-bind="title".

Relative sibling URL in angularJS HTML template

Say i am on a page http://localhost/#/edit/10/step2 and i want to have a link (anchor tag) that takes me to http://localhost/#/edit/10/step1.
What shall one put in ng-href="" and could this be achieved without specifying id (10) in the link?
<a ng-href="step1">Previous</a>
edit (routing):
.config(["$stateProvider", "$urlRouterProvider", "$httpProvider", ($stateProvider: ng.ui.IStateProvider, $urlRouterProvider: ng.ui.IUrlRouterProvider, $httpProvider: ng.IHttpProvider) => {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state("MyModule", {
template: "<div ui-view></div>"
})
.state("home", {
url: "/home",
templateUrl: "App/home.html",
controller: "homeController as ctrl"
});
$httpProvider.interceptors.push("busyHttpInterceptor");
}]);
state (edit):
.state("edit", {
url: "/edit/:id",
templateUrl: "App/edit.html",
controller: "editController",
controllerAs: "ctrl",
resolve: {
}
})
I think you can do the redirection by a ng-click function :
//for the 'state', you can add a new one or edit the existing one depending on your requirement and restirctions
//Add a new one:
.state("edit.action", {
url: "/edit/:id/:action",
templateUrl: "App/edit.html",
controller: "editController",
controllerAs: "ctrl",
resolve: {
}
})
//in the html
<a ng-click=goToAction("step1")>Previous</a>
//in the controller 'editController', inject the service '$stateParams' and '$state'
$scope.goToAction = function(action) {
//get the ':id' from the url
var currentId = $stateParams['id'];
$state.go('edit.action', {
id: currentId,
action: action
});
}
If you want you can also apply regex to the parameter part of the url:
url: "/edit/{id:[a-zA-Z0-9]*}/:action

creating a route Param using ui-router

I am not able set up and maintain an route param. When I set the param. It goes to the correct place. However, if I change the route the content does not change. I tried to make one view object, but home.name state does not render with this approach. I can only get templates to show using two absolute paths.
Could not resolve '#/home/Adam Harvey' from state 'home'
I found a great link https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service
To start: I created a simple list with ng-repeat. Here is a shortened example
$scope.iterants =
[
{
name: 'Adam Harvey',
type: 'Hotel',
dates: '01/21/2015-01/22/2015',
location: 'Rockville Maryland',
status: 'Confirmed'
},
{
name: 'Jana Harvey',
type: 'Hotel',
dates: '01/21/2015-01/22/2015',
location: 'Rockville Maryland',
status: 'Confirmed'
}
];
In my html template I want to place a ui-sref on top of each person's name as a link to view them on another template.
<td><a ui-sref="itinerary.name{{name:person.details}}">{{person.name}}</a></td>
In my config I set up like so with the controller getting passed the $stateParams
.config(function config( $stateProvider ) {
$stateProvider.state( 'home.name', {
url: '/home/:name',
views: {
"main": {
controller: 'AboutCtrl',
templateUrl: 'src/app/about/about.tpl.html'
}
},
data: {pageTitle:'About'}
});
})
.controller( 'AboutCtrl', function AboutCtrl( $scope, $stateParams ) {
$stateParams.name;
});
In the home controller. I have set up my config and controller like so...
.config(function config( $stateProvider ) {
$stateProvider.state( 'home', {
url: '/home',
views: {
"main#": {
controller: 'HomeCtrl',
templateUrl: 'src/app/home/home.tpl.html'
},
resolve: [{
name: ['$stateParams', function($stateParams){
return $stateParams.name;
}]
}]
},
data:{ pageTitle: 'Home' }
});
})
Updates
The issue is your usage of the ui-sref directive. You have to pass the state name and then parameters as an object, like so:
<td><a ui-sref="home.name({ name: person.name })">{{person.name}}</a></td>

How to hide content in the parent view when the user goes to a nested state and show it again when the user backs to the parent one?

I use ui-router and have two nested views.
I’d like to hide some html-content in the parent view when the user goes to child state and show it again when the user backs to parent one.
Could anybody give an advice how to achieve that?
It’s easy to do that using root scope and state change events but it looks like a dirty way, doesn’t it?
app.js
'use strict';
var myApp = angular.module('myApp', ['ui.router']);
myApp.controller('ParentCtrl', function ($scope) {
$scope.hideIt = false;
});
myApp.controller('ChildCtrl', function ( $scope) {
$scope.$parent.hideIt = true;
});
myApp.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('parent', {
url: '/parent',
templateUrl: 'parent.html',
controller: 'ParentCtrl'
})
.state('parent.child', {
url: '/child',
template: '<h2>Child view</h2>',
controller: 'ChildCtrl'
});
});
parent.html
<h2>Parent view</h2>
<div ng-hide="hideIt">
<p>This text should be hidden when the user goes to the nested state.</p>
</div>
<a ui-sref="parent.child">Go to the nested view</a>
<div ui-view></div>
One simple solution is to fill ui-view tag in the parent template with the content that you want gone when child state is loaded.
<ui-view>
<h2>Parent view</h2>
<div ng-hide="hideIt">
<p>This text should be hidden when the user goes to the nested state.</p>
<a ui-sref="parent.child">Go to the nested view</a>
</ui-view>
You should check out named views for this. That would probably be the best way to go. https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
Also, there's another thread that answered this question over here: https://stackoverflow.com/a/19050828/1078450
Here's the working code for nested named views, taken from that thread:
angular.module('myApp', ['ui.state'])
.config(['$stateProvider', '$routeProvider',
function($stateProvider, $routeProvider) {
$stateProvider
.state('test', {
abstract: true,
url: '/test',
views: {
'main': {
template: '<h1>Hello!!!</h1>' +
'<div ui-view="view1"></div>' +
'<div ui-view="view2"></div>'
}
}
})
.state('test.subs', {
url: '',
views: {
'view1#test': {
template: "Im View1"
},
'view2#test': {
template: "Im View2"
}
}
});
}
])
.run(['$state', function($state) {
$state.transitionTo('test.subs');
}]);
http://jsfiddle.net/thardy/eD3MU/
Edit:
Adding some thoughts re the angular-breadcrumbs comment. I haven't used it myself, but at first glance it seems like subroutes shouldn't break the breadcrumbs. I'm just looking at the source code of their demo, around line 62. I'd have to spin it all up to really go about testing it, but it looks like they're doing almost the same thing with specifying views, and it works there: https://github.com/ncuillery/angular-breadcrumb/blob/master/sample/app.js#L62
.state('room', {
url: '/room',
templateUrl: 'views/room_list.html',
controller: 'RoomListCtrl',
ncyBreadcrumb: {
label: 'Rooms',
parent: 'sample'
}
})
.state('room.new', {
url: '/new',
views: {
"#" : {
templateUrl: 'views/room_form.html',
controller: 'RoomDetailCtrl'
}
},
ncyBreadcrumb: {
label: 'New room'
}
})
.state('room.detail', {
url: '/{roomId}?from',
views: {
"#" : {
templateUrl: 'views/room_detail.html',
controller: 'RoomDetailCtrl'
}
},
ncyBreadcrumb: {
label: 'Room {{room.roomNumber}}',
parent: function ($scope) {
return $scope.from || 'room';
}
}
})
Edit2:
This solution will not combine routes into one crumb
See the official demo
re: But I use angular-breadcrumb and in your solution they will be combined into one crum.

default inactive state for ui-router-extras

I am using ui-router-extras to support parallel state for modal windows. When an modal window is open, the "home" state become inactive, but is still visible in the background. This allows me to have deep link for each modal windows.
However, I am having trouble figure out a good way to set the "default" inactive state to "home" if an user come through a modal window link.
I currently define my states like this:
$stateProvider
.state('signup', {
url: '/signup',
onEnter: function($modal) {
$modal.open({
templateUrl: 'singup.html',
size: 'large',
controller: 'SignUpController'
});
}
})
You only posted one state definition!
I tried to get the same working and finally figured it out. If you found a solution could you post it? If not please provide more details
Maybe my solution will help
angular.module('xbmcremoteApp')
.config(function ($stateProvider,$stickyStateProvider) {
$stickyStateProvider.enableDebug(true);
$stateProvider
.state('movies', {
abstract: true,
url: '/movies',
templateUrl: 'app/movies/movies.html',
controller: 'MoviesCtrl'
}).state('movies.gallery', {
url: '',
templateUrl: 'app/movies/movies-gallery/movies-gallery.html',
controller: 'MoviesGalleryCtrl',
sticky:true
}).state('movies.gallery.details', {
url: '/:id',
onEnter: ['$stateParams', '$state', '$modal', '$resource', function ($stateParams, $previousState, $modal, $resource) {
$modal.open({
templateUrl: 'app/movies/movies-gallery/myModalContent.html',
resolve: {
id: function () {
$stateParams.id
}
},
size:'lg',
controller: 'ModalInstanceCtrl'
}).result.then(function () {
return $previousState.go("movies.gallery");
});
}]
});
});
check out ui-router-extras release 0.0.12 and above. I've added support for default substates in DSR. See this github issue for details:
https://github.com/christopherthielen/ui-router-extras/issues/150
And read the updated API docs here: http://christopherthielen.github.io/ui-router-extras/#/dsr
var myState = {
name: 'foo',
url: '/foo/:fooID/:barID',
template: '<div></div>,
controller: 'fooCtrl',
deepStateRedirect: {
default: { state: "foo.bar.baz.defaultSubState", params: { defaultStateParam1: "99" } }
}
}

Resources