Sorry if similar questions have been asked before but I have been strugling to get a certain setup working for a while. I took a working plunker from from an existing question and am trying to tweak it just a little to my needs.
Orginal Plunker: http://plnkr.co/edit/uY1Sl3f0KCTukPGHDRdW
My (slightly) edited fork: http://plnkr.co/edit/hlw4Et00UeGjzxD4Mszi
What I am trying to achieve is a base layout containing a header, footer and unnamed view for the page content. I can do this fine with the original plunker. But when I try to get more fancy and have a structure more like this:
$urlRouterProvider.otherwise('/home/list');
$stateProvider
.state('root', {
abstract: true,
views: {
'#': {
controller: 'RootCtrl',
controllerAs: 'rootCtrl'
},
'header#': {
templateUrl: 'header.html',
controller: 'HeaderCtrl',
controllerAs: 'headerCtrl'
},
'footer#': {
templateUrl: 'footer.html',
controller: 'FooterCtrl',
controllerAs: 'footerCtrl'
}
}
})
And here is the adjusted state definition:
.state('root.home', {
parent: 'root',
url: '/home',
views: {
'#': {
template: '<ui-view></ui-view>',
controller: 'HomeController',
controllerAs: 'homeCtrl'
},
'list#root.home': {
url: '/list',
template: 'homeList.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
});
What I am trying to do here is make it so that 'root.home' state is just a base state for prepending the URL 'home' or whatever the url is in my real application. I have tried ready though the ui-route sample app but it's a lot to take in and am going in circles. I'm sure this is simple...
There is a working updated plunker. There is one state definition adjustment.
This was original piece of code:
.state('root.home', {
parent: 'root',
url: '/home',
views: {
'#': {
template: '<ui-view></ui-view>',
controller: 'HomeController',
controllerAs: 'homeCtrl'
},
'list#root.home': {
url: '/list',
template: 'homeList.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
});
What was wrong there? Firstly a note - we do not need to define parent: 'root', because our parent is in our name 'root.home'. So, to make it more clear, I decided to keep parent setting, while change the state name into 'home'.
Secondly, we have two views in play for our state, but the second one, is ordered to be injected into the first one.
// this line is instructing UI-Router: inject this into
// the other view definition of the current state
// search for ui-view="list"
'list#root.home'
but there was no ui-view="list" defined.
Finally, we cannot declare url for views. Url belongs just to states:
// this is wrong. The view cannot have url
// url is for state
'list#root.home': {
url: '/list',
So, we should introduce the child of our state... 'home.list'
This is the adjusted state(s) definition (from the new working plunker):
.state('home', {
parent: 'root',
url: '/home',
views: {
'#': {
template: '<div ui-view="list"></div>',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
})
.state('home.list', {
url: '/list',
views: {
'list': {
templateUrl: 'homeList.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
});
Related
Trying to get the following url structure to work:
/page/
/page/article
/page/article/third-level-1
/page/article/third-level-2
Ive tried the follow but it doesn't render the article view at all. The page view renders fine:
<section ui-view></section>
$stateProvider
.state('index', {
external: true,
url: '/'
})
.state('page', {
url: '/page',
controller: Controller,
controllerAs: 'ctrl',
templateUrl: '/static/views/page/page.html',
})
.state('page.article', {
url: '/article/',
controller: Controller,
controllerAs: 'ctrl',
templateUrl: '/static/views/page/page-article.html'
});
I then tried everything under the sun, and managed to get the second view to render with the following, however the Controller doesnt run on the article view:
<section ui-view="app"></section>
$stateProvider
.state('index', {
external: true,
url: '/'
})
.state('page', {
url: '/page',
views: {
'app': {
controller: Controller,
controllerAs: 'ctrl',
templateUrl: '/static/views/page/page.html',
}
}
})
.state('page.article', {
url: '/article/',
views: {
'app#': {
controller: Controller,
controllerAs: 'ctrl',
templateUrl: '/static/views/page/page-article.html',
}
}
});
How can i get the child view to render and use the/a controller? Haven't even gotten down to the third level.
It should be this.
.state('page.article', {
url: '/page/article/',
views: {
'app#': {
controller: Controller,
controllerAs: 'ctrl',
templateUrl: '/static/views/page/page-article.html',
}
}
Problem:
When I navigate to #/ it tries to load the profile state which is at #/:userId.
So I'm completely perplexed by this functionality as it is seemingly intermittent. I already referred to this question and it seems that shuffling the order has no affect.
I want to have clean routes with UI-Router:
#/ This is the user's root dashboard
#/123 This is a specific user profile
#/my/preferences This is some other route.
$stateProvider
.state('profile', {
abstract: true,
url: '/:userId',
templateUrl: 'profile-user.html',
controller: 'ProfileController',
controllerAs: 'vm',
reloadOnSearch: false,
resolve: {
data: function() {
// some promises stuff
}
}
})
.state('profile.activity', {
url: '',
templateUrl: 'activity.html'
})
.state('dashboard', {
url: '/',
templateUrl: 'dashboard.html',
controller: 'DashboardController',
controllerAs: 'vm',
reloadOnSearch: false,
resolve: {
data: function() {
// some promises stuff
}
}
})
.state('preferences', {
url: '/my/preferences',
templateUrl: 'preferences.html',
controller: 'PreferencesController',
controllerAs: 'vm',
reloadOnSearch: false,
resolve: {
data: function() {
// some promises stuff
}
}
})
Question:
Is there a way to have #/, #/:param and #/someRoute/:someId be different states in UI-Router? Also, is there a way to see what routes are registered and in what order in UI-Router? That would be tremendously helpful during debugging.
The order is essential when UI-Router tries to resolve states. So define more specific state should be defined sooner then generic states:
// the specific will be checked first
.state('dashboard', {
url: '/',
...
.state('preferences', {
url: '/my/preferences',
...
// these will be used if above not matched
.state('profile', {
abstract: true,
url: '/:userId',
...
just a quick question. Can named views in the ui-router for angular have routes and an url? And if so, how can I activate them?
I searched through the wiki, but can't find any info on that.
What I want is a app with three different child routes so only one can be active at a time, but they're supposed to be in different views, so I can nicely animate between them with an accordion effect.
Any help there?
Thanks!
EDIT: Here's some code of my routing so far:
function routeConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
//templateUrl: 'app/main/main.html',
//controller: 'MainController',
//controllerAs: 'main',
views: {
'' : {
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
},
'contact': {
templateUrl: 'app/contact/contact.html',
controller: 'ContactController',
controllerAs: 'contact'
},
'profile': {
templateUrl: 'app/profile/profile.html',
controller: 'ProfileController',
controllerAs: 'profile'
},
'works': {
templateUrl: 'app/works/works.html',
controller: 'WorksController',
controllerAs: 'works'
}
}
});
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
}
I'd recommend just creating different states for each view. There's no reason you can't animate smoothly between different states.
So:
function routeConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
})
.state('home.contact', {
templateUrl: 'app/contact/contact.html',
controller: 'ContactController',
controllerAs: 'contact'
})
.state('home.profile', {
templateUrl: 'app/profile/profile.html',
controller: 'ProfileController',
controllerAs: 'profile'
params: {
"user" : {}
}
})
.state('home.works', {
templateUrl: 'app/works/works.html',
controller: 'WorksController',
controllerAs: 'works'
})
}
});
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
}
In your ui-sref links, you can pass data to those views using parameters, like this: <a ui-sref="home.profile({user: contact.user}) along with the 'params' section in the state definition as I've included above.
Routing is serverside so if you call any address your serverside routing needs to launch proper html or javascripts which will let you render what you want.
For more accurate answer please respond with more details: what is your serverside engine, which version of angular you use etc.
i make an mobile site for buy/renew/transfer/ domains.
The whole app has 4 templates connected into functional chain.
Buy : Search -> (login if needed?) -> Pay -> -Confirmation
Renew : Choose -> (login if needed?) -> Pay -> -Confirmation
Transfer: Choose -> (login if needed?) -> Pay -> -Confirmation
While the app has the same templates, the functionality and titles are different. And i want to be able to check the parent state within every state in order to make dynamic changes, and switch request strings.
The simplest way is to define 12 (4X3) routes in my stateProvider. but i'm looking for more effective way to do this by unite buy.search, renew.search, transfer.search and others in three groups of routes. is it possible? Do any one may suggest me other approach?
Thanks
===UPDATE===
current stateProvider
.state('app.buy.search', {
url: "/search",
templateUrl: "templates/search_domain.html",
controller: 'SearchCtrl'})
.state('app.buy.login', {
url: "/buy/login",
templateUrl: "templates/login.html",
controller: 'LoginCtrl'})
.state('app.buy.pay', {
url: "/buy/pay",
templateUrl: "templates/pay.html",
controller: 'PayCtrl'})
.state('app.renew.search', {
url: "/search",
templateUrl: "templates/search_domain.html",
controller: 'SearchCtrl'})
.state('app.renew.login', {
url: "/buy/login",
templateUrl: "templates/login.html",
controller: 'LoginCtrl'})
.state('app.renew.pay', {
url: "/buy/pay",
templateUrl: "templates/pay.html",
controller: 'PayCtrl'})
.state('app.transfer.search', {
url: "/search",
templateUrl: "templates/search_domain.html",
controller: 'SearchCtrl'})
.state('app.transfer.login', {
url: "/buy/login",
templateUrl: "templates/login.html",
controller: 'LoginCtrl'})
.state('app.transfer.pay', {
url: "/buy/pay",
templateUrl: "templates/pay.html",
controller: 'PayCtrl'})
You can reduce the router configurations by applying dynamic url. In your case, pages (search, pay, login) are same for modules (buy, renew, transfer). So you can change the configuration as follows
$stateProvider
.state('app', {
url: '/',
templateUrl: 'dashboard.html',
controller: 'MainCtrl'
})
.state('app.search', {
url: '{module}/search',
views: {
"searchView": {
templateUrl: 'search.html',
controller: 'SearchCtrl'
}
}
})
.state('app.pay', {
url: '{module}/pay',
views: {
"payView": {
templateUrl: 'pay.html',
controller: 'PayCtrl'
}
}
})
.state('app.login', {
url: '{module}/login',
views: {
"loginView": {
templateUrl: 'login.html',
controller: 'LoginCtrl'
}
}
})
Demo: http://plnkr.co/edit/NGsZJB?p=preview
How do I load different layouts ?
Currently I have three layouts for my backend, one for admin, one for user and last for teacher i.e adminLayout.html, userlayout.html and teacherLayout.html for dashboards.
I am writing my routes something like this -
app.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'views/pages/home.html',
controller: 'homeCtrl'
})
.when('/users/login', {
templateUrl: 'views/users/login.html',
controller: 'usersLoginCtrl'
})
.when('/users/dashboard', {
templateUrl: 'views/users/dashboard.html',
controller: 'usersDashCtrl'
})
.when('/teachers/login', {
templateUrl: 'views/teachers/login.html',
controller: 'teachersLoginCtrl'
})
.when('/teachers/dashboard', {
templateUrl: 'views/teachers/dashboard.html',
controller: 'teachersDashCtrl'
})
});
For /users/dashboard I want usersLayout.html and /teachers/dashboard I want teachersLayout.html.
How could I acheive this ?
I tried $window.location.href = "LINK_TO_LAYOUT"; but its is taking the whole path in the URL, however I want to my URL like -
mysite.com/teachers/dashboard
mysite.com/users/dashboard
mysite.com/admin/dashboard
You should use Ui-Router.
It support nested views.
So in your example your routes would be like this.
app.config(function($stateProvider){
$stateProvider
.state('main', {
url: '/',
templateUrl: 'views/pages/home.html',
controller: 'homeCtrl'
})
.state('users', {
url: '/users',
templateUrl: 'views/users/layout.html'
})
.state('users.login', {
url: '/users/login',
templateUrl: 'views/users/login.html',
controller: 'usersLoginCtrl'
})
.state('users.dashboard', {
url: '/users/dashboard',
templateUrl: 'views/users/dashboard.html',
controller: 'usersDashCtrl'
})
.state('teachers', {
url: '/teachers',
templateUrl: 'views/teachers/layout.html'
})
.state('teachers.login', {
url: '/teachers/login',
templateUrl: 'views/teachers/login.html',
controller: 'teachersLoginCtrl'
})
.state('teachers.dashboard', {
url: '/teachers/dashboard',
templateUrl: 'views/teachers/dashboard.html',
controller: 'teachersDashCtrl'
})
});
Then you need to creat this new Layout Pages.
On: views/users/layout.html
<div id="usersLayout">
<ui-view/>
</div>
On: views/teachers/layout.html
<div id="teachersLayout">
<ui-view/>
</div>
Hope this get you going.
One of ways use 'abstract' state from ui-router
$stateProvider
.state('contacts', {
abstract: true, // <<< this is your layout
url: '/contacts',
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
// >>> Or use templateUrl: 'contactLayout.html'
template: '<ui-view/>'
})
.state('contacts.list', {
// url will become '/contacts/list'
url: '/list'
//...more
})
.state('contacts.detail', {
// url will become '/contacts/detail'
url: '/detail',
//...more
})
Please spend some time for learning ui-router and you will have powerfull and simple tool for routing in angularjs.
Check docs for more info about abstract state.