Nested Views and Routing for Angularjs
Overview for CincyNg Meetup
Union of Rad
Graphic Designer turned
eLearning Course Designer turned
Flash Animator turned
Flash/Flex Developer turned
Web UI/UX Designer turned
Front-end Web Developer turned ?
Researching JavaScript frameworks for project.
Angular: Easy, Fun, Familiar
UI-Router's solution
$stateProvider.state('contact.detail', {
url: '/contacts/:id',
template: '<h1>Hello</h1>',
templateUrl: 'contacts.html',
controller: function($scope){ ... },
resolve: { ... }
})
$routeProvider.when('/contacts/:id', {
template: '<h1>Hello</h1>',
templateUrl: 'contacts.html',
controller: function($scope){ ... },
resolve: { ... }
})
ngRoute
ui.router
Main method of adding routes
1.2 changes to route()
Just for creating url redirects
To use when or otherwise, $urlRouterProvider
$urlRouterProvider
.when('/user/:id', '/contacts/:id') .otherwise('/');
index.html
<body>
<ui-view/>
</body>
app.js
.state('top', { template:"<ui-view/>"
}) .state('top.middle', { template:" <ui-view/>"
<ui-view/>" }) .state('top.middle.bottom', { template:"
})
How baby states are made.
$stateProvider
.state("home", { ... });
.state("contacts", { ... });
.state("contacts.detail", { ... });
.state("contacts.detail.edit", { ... });
The dot in the state names auto-denotes parental hierarchy.
It knows that 'contacts.detail' is a child of 'contacts'.
1. $stateProvider
.state('contacts', {}) .state('contacts.list', {});
2. $stateProvider
.state('contacts', {}) .state('list', { parent: 'contacts' });
var contacts = {
name: 'contacts', //mandatory
templateUrl: 'contacts.html'
}
var contactsList = {
name: 'list', //mandatory
parent: contacts, //mandatory
templateUrl: 'contacts.list.html'
}
$stateProvider
.state(contacts)
.state(contactsList)
.state('parent', {
resolve:{
resA: function(){
return {'value': 'A'};
}
},
controller: function($scope, resA){
$scope.resA = resA.value;
}
})
.state('parent.child', {
resolve:{
resB: function(resA){
return {'value': resA.value + 'B'};
}
},
controller: function($scope, resA, resB){
$scope.resA2 = resA.value;
$scope.resB = resB.value;
}
$stateProvider
.state('parent', { data:{ customData1: "Hello", customData2: "World!" } }) .state('parent.child', { data:{ // customData1 inherited from 'parent' // but we'll overwrite customData2 customData2: "UI-Router!" } }); $rootScope.$on('$stateChangeStart', function(event, toState){ var greeting = toState.data.customData1 + " " + toState.data.customData2; console.log(greeting); })
When 'parent' is activated it prints 'Hello World!'
When 'parent.child' is activated it prints 'Hello UI-Router!'
$stateProvider.state("contacts", {
template: '<h1>{{title}}</h1>',
resolve: { title: 'My Contacts' },
controller: function($scope, title){
$scope.title = 'My Contacts';
},
onEnter: function(title){
if(title){ ... do something ... }
},
onExit: function(title){
if(title){ ... do something ... }
}
})
myApp.controller('contactCtrl', ['$scope', '$state',
function($scope, $state){
$scope.goToDetails = function(){
$state.go('contact.details', {id: selectedId});
}
}
Go to parent - $state.go('^')
Go to child - $state.go('.3')
Go to sibling - $state.go('^.1')
Absolute Path - $state.go('3.3')
Hey Cous! - $state.go('^.^.2.1')
<a ui-sref="home">Home</a>
<a ui-sref="home" href="#/home">Home</a>
<li ng-repeat="contact in contacts">
<a ui-sref="contacts.detail({ id: contact.id })"</a>
</li>
<a ui-sref='^'>Home</a>
In theory...
one could build an app using ui-router that associated not a single url with any state. They could navigate via go() and ui-sref....In theory.
$stateProvider
.state('contacts', {
url: '/contacts',
})
.state('contacts.list', {
url: '/list',
});
$stateProvider
.state('contacts', {
url: '/contacts',
})
.state('contacts.list', {
url: '^/list',
});
url: '/contacts/:contactId'
url: '/contacts/{contactId}'
url: '/contacts/{contactId:[0-9a-fA-F]{1,8}}' //Hexadecimals
url: '/contacts?contactId&contactRegion' //Separate with '&'
//State URL:
url: '/users/:id/details/{type}/{repeat:[0-9]+}?from&to'
//Navigate to:
'/users/123/details//0' //$stateParams will be
{ id:'123', type:'', repeat:'0' }
//Navigated to:
'/users/123/details/default/0?from=there&to=here'
//$stateParams will be
{ id:'123', type:'default', repeat:'0',
from:'there', to:'here' }
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
resolve: { depA: function(){
return $state.current.params.contactId + "!" };
}, controller: function($stateParams){ $stateParams.contactId // Exists! }
}).state('contacts.detail.subitem', { url: '/item/:itemId', controller: function($stateParams){ $stateParams.contactId // Doesn't exist $stateParams.itemId // Exists!
} })
{ name: '', url: '^', 'abstract': true
}
$stateProvider
.state('deep.down.state.mainbits', {
url: "url/still/goes/up/here"
views: {
'main@': { ... },
'sidenav@': { ... }
}
})
$stateProvider .state('report', { url: "url/still/goes/up/here" views: { 'main': { ... }, 'sidenav': {
templateUrl: "sidenav.html",
controller: "SideNavCtrl"
} } })