Creating layouts with multiple nested views using angular-ui-router - angularjs

I have tried several examples on using the ui-router and the state manager. My nested views and routes are not working as I hoped. Here is an example of how I am configuring the states:
$stateProvider
.state("main", {
abstract: true,
url: "/main",
views: {
"layout": {
templateUrl: "main.index.html"
},
"mainNavigation#main": {
templateUrl: "main-navigation-partial.html"
}
},
onEnter: function() {
console.log("enter main");
}
})
.state("main.dashboard", {
url: "/dashboard",
views: {
"container#main": {
templateUrl:"main-dashboard.html"
}
}
});
As you can see, I have an abstract state named main. All main views will use the mainNavigation view. There is also a container view area where the content for each section will reside. There is an index.html that will be used by all states. So, I may, down the road have an abstract state name client with accompanying states and views.
I can see the individual html files being loaded, but the views are not being populated in the correct named view areas. I have created a plunk that demonstrates how I want to manage my templates and views.

Your main state is loading main.index.html into a ui-view named layout. In your plunker, your root ui-view is unnamed. So to fix this, add a name to that ui-view.
http://plnkr.co/edit/xKDcuk99OACQR73LR0hf?p=preview
<div ui-view='layout'>
Or, you could leave the ui-view unnamed and change the view to reflect that.
"": {
templateUrl: "main.index.html"
}
For more on view naming, see the ui-router wiki.

Related

UI Router update parent view from child

I'm new to using Angular UI Router and I seem to be having difficulty being able to update a parent view from it's child view.
I have the following HTML structure (restructured for easier reading, obviously views are in separate html files).
<div ui-view="main">
{ main content }
<div ui-view="tab">
{ tabbed content }
</div>
</div>
Inside tab I have the following sref:
<span ui-sref="silverstone.platforms.view({_id: platform._id})">{{platform.name}}</span>
And here are my states: (I'm using webpack, hence require)
$stateProvider
.state('silverstone', {
url: '/silverstone',
views: {
'main': {
controller: 'SilverstoneCtrl',
template: require('./templates/index.html')
}
}
});
$stateProvider
.state('silverstone.platforms', {
url: '/platforms',
views: {
'tab': {
controller: 'SilverstoneCtrl',
template: require('./templates/platforms.html')
}
}
});
$stateProvider
.state('silverstone.platforms.view', {
url: '/:_id',
views: {
'main': {
controller: 'SilverstoneCtrl',
template: require('./templates/platform-view.html')
}
}
});
When the above sref is clicked, the "main" view needs to be updated. The URL is updating but the views aren't...?
I was missing # in my silverstone.platforms.view state to explicitly address the parent view.
$stateProvider
.state('silverstone.platforms.view', {
url: '/:_id',
views: {
'main#': {
controller: 'SilverstoneCtrl',
template: require('./templates/platform-view.html')
}
}
});
Use reload: true parameter in yout ui-sref links like this.
ui-sref="silverstone.platforms.view({_id: platform._id})" ui-sref-opts="{reload: true}"
Edit:
Maybe your problem are caused by nested states combined with flat template structure.
Other solution may be to properly nest your templates, as states.
For example we have states app and app.substate, then we have two templates for both states. Tempalte of app state contains ui-view directive. (that means every state contains new ui-view directive for injecting of substate template). States are nested by default, this would represent appropriately nested templates.

Angular, set ui-view inside ui-view

I have a question about multiple views. It's difficult to explain but I'll try:
Navigating to state 'About' and setting template url for ui-view 'columnOne' and ui-view 'columnTwo' was done succesfully
.state('about', {
url: '/about',
views: {
// the main template will be placed here (relatively named)
'': { templateUrl: 'partial-about.html' },
// the child views will be defined here (absolutely named)
'columnOne#about': { template: 'Look I am a column!' },
// for column two, we'll define a separate controller
'columnTwo#about': {
templateUrl: 'table-data.html',
controller: 'scotchController'
}
}
});
Now I would like to set the templateUrl of view 'columTwo' from view 'columnOne'.
How is this done? Is it possible?
The example your taking from there website is parallel view example not nested view nested view can be made by making a page and than making other states with . like registration is a page and multistep form than the page containing registration uiview will we state registration and the parts with be like registration.contact,registration.acadamics, registration.extraactivities. And really man there documentation is quiet confusing

Using UI-Router multiple states with different URLs

I am trying to develop a UI for my designer but have ran into a bit of a problem trying to get UI-Router and Angular to work correctly in this manner. On the Home page I have 2 sections, Users and Groups. The Home page has a URL of /home and I want to be able to select a User OR a Group and have the URL change to either /home/user/:id or /home/group/:id respectively. The problem is that I want the nested view to appear directly below the corresponding section. So if they select a User, it will open up the User view underneath the Users section and vice versa with Groups.
I thought this could be acheived with multiple views like <div ui-view="users"></div> and <div ui-view="groups"></div>, but there is no sense of state when using this. The views just render automatically regardless of the URL (state).
Is there a way to achieve this using ui-router by maintaining state whilst utilizing 2 views?
Plunker: http://plnkr.co/edit/vfz1l4GAdBdhkyC6zMgQ?p=preview
You can create an abstract state to create a layout, then reference that state as parent to other states.
Here's a plunker
$stateProvider.state('home', {
abstract: true,
views: {
'#': {
templateUrl: 'home.html',
},
'user#home': {},
'group#home': {
templateUrl: 'group.html'
}
}
}).state('root', {
parent: 'home',
url: '/',
views: { . . }
}).state('home.user', {
parent: 'home',
url: '/user',
views: {
'user#home': {
controller: 'UserController',
templateUrl: 'user.html'
},
'group#home': {}
}
})

How do I prevent reload on named view, when state changes? AngularJS UI-Router

I'm using the excellent ui-router module in my application. As part of this, I'm using named views to manage the 'dynamic sub-navigation' I have in the app.
Consider the following:
$urlRouterProvider.otherwise('/person/list');
$stateProvider
.state('person', {
url: '/person',
abstract: true,
})
.state('person.list', {
url: '/list',
views: {
"main#": {
templateUrl: "person.list.html",
controller: 'PersonListController'
}
}
})
.state('person.details', {
url: '/{id}',
views: {
'main#': {
templateUrl: "person.details.html",
controller: 'PersonController'
},
'nav#': {
templateUrl: "person.nav.html",
controller: 'PersonNavController'
}
}
});
When users first visit the app, they are presented with a list of people. When they click on a person, they are taken to the details page. Pretty basic stuff. Here's the markup if it helps...
<div>
<aside ui-view="nav"></aside>
<div ui-view="main"></div>
</div>
However, the PersonNavController calls a REST service to get a list of people, so when viewing a person, the user is able to navigate sibling elements. Using the method above causes the template and controller to re-render, thus causing a delay after every click, despite the content never changing.
Is there a way to keep the 'nav#' view loaded, and only refresh the 'main#' view?
The way I am using ui-router in this scenarios is: move the views to the least common denominator.
Other words: In case that ui-view="nav" is shared among all the details and is the same for all of them (because it should be loaded only once) - it should be part of the list state (parent of the detail state)
the parent state defintion would be adjusted like this:
.state('person.list', {
url: '/list',
views: {
"main#": {
templateUrl: "person.list.html",
controller: 'PersonListController'
}
// here we target the person.list.html
// and its ui-view="nav"
'nav#person.list': {
templateUrl: "person.nav.html",
controller: 'PersonNavController'
}
}
So where is the trick? In the power of the angular ui-router. We can, during each state defintion, target the current view. Now, the nav view is part of the list state definition - i.e. it will not be reloaded during the detail switching (also check here for more explanation)
We just have to use the defined naming conventions, see:
View Names - Relative vs. Absolute Names
Few cited lines from the mentioned documentation:
views: {
////////////////////////////////////
// Relative Targeting //
// Targets parent state ui-view's //
////////////////////////////////////
// Relatively targets the 'detail' view in this state's parent state, 'contacts'.
// <div ui-view='detail'/> within contacts.html
"detail" : { },
// Relatively targets the unnamed view in this state's parent state, 'contacts'.
// <div ui-view/> within contacts.html
"" : { },
///////////////////////////////////////////////////////
// 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
"info#contacts.detail" : { }
// Absolutely targets the 'detail' view in the 'contacts' state.
// <div ui-view='detail'/> within contacts.html
"detail#contacts" : { }

Angular ui tab with seperate controllers for each tab

I would like to make a bootstrap tabset with each tab having it's own controller. Can anyone point me in which direction I should go.
Currently I have made several difference controllers, which I would like to be used in a tabset instead of having them displayed as a different route.
I know I could fake it by having the tabset in the difference controller templates displaying the given controllers tab as active, but I would like to be able to have a main TabController with several child controllers (for each tab)
If you are using angular ui router you can use nested states to do this.
Create an abstract state with a view that contains the tabs and a nested ui-view
Create a child state for each of your tabs, each inheriting from the abstract state
Each child state can set the content of the nested ui-view, and define a controller
$stateProvider.state( 'tabs', {
abstract: true,
url: 'tabs',
views: {
"tabs": {
controller: 'TabsCtrl',
templateUrl: 'tabs.html'
}
}
})
.state('tabs.tab1', {
url: '', //make this the default tab
views: {
"tabContent": {
controller: 'Tab1Ctrl',
templateUrl: 'tab1.html'
}
}
})
.state('tabs.tab2', {
url: '/tab2',
views: {
"tabContent": {
controller: 'Tab2Ctrl',
templateUrl: 'tab2.html'
}
}
});
Why don't you put a directive on each tab that has it's own controller? If you are using 1.x. Separate your code out by directive not tabs

Resources