I'm working on a complex UI architecture based on Angular and Angular UI Router. I'm trying to define routes with nested ui-views on multiple modules.
Here is what I'm trying to do: http://plnkr.co/edit/sxJOPQAgyEZfcYfUReGR?p=preview
Files here:
index.html
<body ng-app="app">
<h1 ui-view="title"></h1>
<div ui-view="sidebar1"></div>
<ul ui-view="sidebar2"></ul>
<div ui-view="content"></div>
</body>
app.js
angular
.module('app', ['ui.router', 'page1'])
.config(['$locationProvider','$stateProvider', '$urlRouterProvider',
function ($locationProvider, $stateProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true);
$stateProvider.state({
name: "page1",
url: "/page1",
abstract: true
});
$urlRouterProvider.otherwise('/page1');
}]);
page1.js
angular
.module('page1', ['ui.router'])
.config(function ($stateProvider) {
$stateProvider.state({
name: 'page1.main',
views: {
title: {
template: "My Title"
},
sidebar1: {
template: "<ul><li ng-repeat='item on items'>{{item}}</li></ul>",
controller: function($scope) {
$scope.items = ['foo1', 'bar1'];
}
},
sidebar2: {
template: "<ul><li ng-repeat='item on items'></li></ul>",
controller: function($scope) {
$scope.items = ['foo2', 'bar2'];
}
},
content: {
template: "<div ng-repeat='one in many'>{{one}}</div>",
resolve: {
stuff: function () {
return [1,2,3,4,5]
}
},
controller: function($scope, stuff) {
$scope.many = stuff;
}
}
}
});
});
What am I missing?
Thanks a lot in advance.
I've made few changes, and make it running here.
Firstly, as defined in doc: Abstract States, child state of an abstract state must be defined, i.e. must have some url defined (which will help ui-router to find out which state to use... abstract parent is unreachable)
$stateProvider.state({ name: 'page1.main', url : '/main',
And also the default route was changed to:
$urlRouterProvider.otherwise('/page1/main');
And the most important thing is to use correct ui-view naming:
$stateProvider.state({
name: 'page1.main',
url : '/main',
views: {
"title@": {
template: "My Title"
},
"sidebar1@": {
template: "<ul><li ng-repeat='item on items'>{{item}}</li></ul>",
controller: function($scope) {
$scope.items = ['foo1', 'bar1'];
}
},
"sidebar2@": {
template: "<ul><li ng-repeat='item in items'>{{item}}</li></ul>",
controller: function($scope) {
$scope.items = ['foo2', 'bar2'];
}
},
"content@": {
...
What we can see, the view names are suffixed with the @, which means: search for them in the top root, unnamed view (usually index.html)
See more here: View Names - Relative vs. Absolute Names
a small extract from doc:
///////////////////////////////////////////////////////
// Absolute Targeting using '@' //
// Targets any view within this state or an ancestor //
///////////////////////////////////////////////////////
// Absolutely targets the 'info' view in this state, 'contacts.detail'.
// <div ui-view='info'/> within contacts.detail.html
"[email protected]" : { }
// Absolutely targets the 'detail' view in the 'contacts' state.
// <div ui-view='detail'/> within contacts.html
"detail@contacts" : { }
// Absolutely targets the unnamed view in parent 'contacts' state.
// <div ui-view/> within contacts.html
"@contacts" : { }
The working plunker.
EDIT: How to preserve the /page1 in url
As (almost) always with ui-router, we can give us this behaviour. The trick is, to reset url evaluation to start on the root level - even for child (without parent url part). And this could be done with a magical "^" sign
$stateProvider.state({
name: 'page1.main',
url : '^/page1',
views: {
....
Here is doc:
(a cite)
If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With