I'm trying to set my application to works with 2 layouts (one without sidebars, one with 2 sidebars), this is my solution:
$stateProvider
.state('main', {
url: "/",
abstract:true,
templateUrl: "/layouts/main.html"
})
.state('sidebars', {
url: "/",
abstract:true,
templateUrl: "/layouts/two-sidebar.html"
})
.state('home', {
parent:'main',
templateUrl: "/partials/home.html"
})
.state('about', {
url: "about",
parent:'sidebars',
templateUrl: "/partials/about.html"
})
main.html
<div class="container">
<div ui-view class="view"/>
</div>
two-sidebar.html
<div class="container-fluid">
<div class="row">
<div class="col-md-2">leftcontent</div>
<div class="col-md-8">
<div ui-view class="view"></div>
</div>
<div class="col-md-2">rightcontent</div>
</div>
</div>
I'm sure there are better solutions, but with this all works fine.
The only problem is when I visit the root page /#/ the first time I get a blank page, when I click on home the url is the same but it works fine.
To be more clear, here the plunker, to see the problem you have to open it in an external windows (the blue button in the preview window): http://plnkr.co/edit/Q4cZM69hn0lutYEYjmxH?p=preview
EDIT: It looks like the main problem was the missing empty url
.state('home', {
url:"",
parent:'main',
templateUrl: "/partials/home.html"
})
You have defined two states bound to the same URL (/).
According to UI Router's design, only one state should be bound to a URL.
If you want to have two states with the same URL, make the second one the child state and let it have nothing in it's URL prop like so:
.state('main', {
url: "/",
abstract:true,
templateUrl: "/layouts/main.html"
})
.state('main.sidebars', {
url: "",
templateUrl: "/layouts/two-sidebar.html"
})
Change it like this,
.state('main', {
url: "/",
abstract:true,
templateUrl: "/layouts/main.html"
})
.state('sidebars', {
url: "/something",
abstract:true,
templateUrl: "/layouts/two-sidebar.html"
})
Related
I have the following arrangement:
$stateProvider.state('home', {
url: '/',
template: ''
})
.state('profile', {
url: '/profile/view',
templateUrl: 'static/templates/profile.tpl.html'
})
.state('profile.view', {
url: '',
templateUrl: 'static/templates/profile-view.tpl.html',
controller: 'profileController',
controllerAs: 'pc'
})
.state('profile.edit', {
url: '/edit',
templateUrl: 'static/templates/profile-edit.tpl.html',
controller: 'editProfileController',
controllerAs: 'editCtrl'
})
;
What I intend to do is - I have some common partial content between the profile.view and the profile.edit states.
The common part is supposed inside the profile state. But the current arrangement is failing and /profile/view DOES NOT render any of the partials.
No errors reported to console.
Edit:
Here is profile.tpl.html
<div flex flex-gt-sm="50" flex-offset-gt-sm="25" layout="row" layout-align="center">
<div ui-view>
</div>
</div>
Edit 2:
After adding abstract: true the profile.view state started working fine. But profile.edit state keeps redirecting to /. Sort of following the .otherwise('/') rule
I'll answer my own question:
All I was missing was abstract: true in the profile state
Edit:
following things completely solved it for me:
abstract: true in profile state
url: '/profile' in profile state
url: '/view' in profile.view state
url: '/edit' in profile.edit state
I have a basic Index.html file which following structure:
<body class="{{$state.current.name.replace('.','-')}}">
<div ui-view>
<div ng-include src="'partials/menu.html'"></div>
<!-- <div ng-menu class="ui top blue sidebar menu active"></div> -->
<div class="view-height-100"></div>
</div>
...
</body>
When I am in the login state, it's working very well:
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'partials/login-area.html',
controller: 'LoginController',
});
But, when I am routing to the user.management state, nothing gets shown (but Chrome is loading the template, so I can access the scope and the .html file is there):
$stateProvider
.state('user', {
url: '/:buildingName',
controller: 'CurrentBuildingController',
data: {
access: ['user']
}
})
.state('user.management', {
url: '/management',
templateUrl: '/views/management.html',
controller: 'ManagementController'
})
Can someone explain me why?
Parent state simply must have target for its child (unless we use absolute naming to target some super parent, but it is another approach)
.state('user', {
url: '/:buildingName',
template: "<div ui-view></div>",
controller: 'CurrentBuildingController',
data: {
access: ['user']
}
})
see that we now have template: "<div ui-view></div>", which will serve as a view target for any child state 'user.xxx'
Check also:
AngularJS UI-Router : Abstract state + child states not working
EXTEND - let child to target the index.html
We can use absolute naming and child will then be injected directly into index.html. There is a working plunker (by intention parent won't load, it does not have any template)
.state('parent', {
url: "/parent",
//templateUrl: 'tpl.html',
})
.state('parent.child', {
url: "/child",
views: {
'#': {
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
}
}
})
Check this for more info:
Angularjs ui-router not reaching child controller
I have an app which has three views (ui-view using Angular ui-router):
header, sidebar and content.
my index.html looks like this: (I omitted the actual classes for clearness)
<body>
<div ui-view="header" class="..."></div>
<div class="page-container">
<div ui-view="sidebar" class="..."></div>
<div class="page-content">
<div ui-view="content"></div>
</div>
</div>
</div>
</body>
This pattern works well with pages that have the header and sidebar.
But I have some pages that I don't want to display the header and sidebar, for example a login page that should fit on all page.
For this kind of pages I need something like:
ui-view which should look like this:
<body>
<div ui-view="content"></div>
</body>
So it won't be nested and under the other views <div>'s and affected by their classes.
I have some solutions in mind, but none of them gave me a good enough UX.
I tried adding <ng hide> to the header and sidebar depending on the state. It worked but there was annoying flickering (that I couldn't eliminate with ng-cloak for some reason..)
To make things more clear, here is an example of two states , one is "one pager" and the other is full page with header and sidebar:
.state('Login', {
url: '/login',
views: {
'content': {
templateUrl: './../templates/login.html',
controller: 'LoginCtrl'
}
}
})
.state('Users', {
url: '/users',
views: {
'header': {
templateUrl: './../templates/header.html',
controller: 'HeaderCtrl'
},
'sidebar': {
templateUrl: './../templates/sidebar.html',
controller: 'SidebarCtrl'
},
'content': {
templateUrl: './../templates/users.html',
controller: 'UsersCtrl'
}
}
})
I also think using nested views, but not sure whether this is the right approach.
Maybe try using nested states, ie:
.state('app', {
url: '/app',
abstract: true,
templateUrl: './../templates/treeViewTemplate.html'
})
.state('login', {
url: '/login',
templateUrl: './../templates/login.html',
controller: 'LoginCtrl'
})
.state('app.users', {
url: '/users',
views: {
'header': {
templateUrl: './../templates/header.html',
controller: 'HeaderCtrl'
},
'sidebar': {
templateUrl: './../templates/sidebar.html',
controller: 'SidebarCtrl'
},
'content': {
templateUrl: './../templates/users.html',
controller: 'UsersCtrl'
}
}
})
In your root abstract state you define a template for 3 view-layout. login state will instead take whole display.
I've looked at countless examples of how to set this up. Many right here at SO. But nothing is working in my case. It's a very simple set of two views, one nested below the first. Second ui-view never loads...
Here is the simple index.html...
<body ng-app="d6Games">
<div ui-view="home"></div>
</body>
Here is the simple child view, this is inside home.html template...
<div class="d6body bilbo">
<div ui-view="content"></div>
</div>
Here are the simple states...
.state('home', {
url: '/home',
views: {
'home': {
templateUrl: '/views/home.html'
}
}
})
.state('home.intro', {
url: '/intro',
views: {
'content': {
templateUrl: '/views/game-intro.html'
}
}
})
The first /views/home.html template loads fine, as expected, however the child /views/game-intro.html never loads. It's just html and text and it's in the same folder as home.html.
What am I missing?
There is a working plunker
I just changed the template path (removed the leading '/'), and all is working (however this was required for plunker, not sure about your environment and path settings):
$stateProvider
.state('home', {
url: '/home',
views: {
'home': {
templateUrl: 'views/home.html'
}
}
})
.state('home.intro', {
url: '/intro',
views: {
'content': {
templateUrl: 'views/game-intro.html'
}
}
})
}
Check that in action here
I am trying to create a page where I have a fixed header and changing content, but the fixed header depends on the state route, I would also like the header and the content to have different controllers and templates.
For example for the URL
/user/:userId/profile
I would like the header to display the user name, so it needs to know the value of :userId.
I can achieve this by used named views and ui-router, but here us code duplication that I want to avoid
$stateProvider
.state('profile', {
url: '/user/:user_id/profile',
views: {
'header': {
templateUrl: 'user-header.html',
controller: 'HeaderController'
},
'info': {
templateUrl: 'profile.html',
controller: 'ProfileController'
}
}
})
.state('friends', {
url: '/user/:user_id/friends',
views: {
'header': {
templateUrl: 'user-header.html',
controller: 'HeaderController'
},
'info': {
templateUrl: 'friends.html',
controller: 'FriendsController'
}
}
})
<section id="startup-header" ui-view="header">
</section>
<section ui-view="info">
</section>
How can I define the header once, but have the content defined per content type.
I hope I formulate the questions in a way it's clear what I want to achieve.
Ok. Let's try this:
You can create a parent page with your header for user's profile that will be contain nested child pages:
<div id="header">
<a ui-sref="userPage.profile">Profile</a>
<a ui-sref="userPage.friends">Friends</a>
......
</div>
<div ui-view>
</div>
Read more about ui-sref ditective here
And in $stateProvider something like:
$stateProvider.state('userPage.profile', {
url: '/user/:user_id/profile',
templateUrl: 'profile.html',
controller: 'ProfileController'
}
}).state('friends', {
url: '/user/:user_id/friends',
templateUrl: 'friends.html',
controller: 'FriendsController'
}
})