Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

This is going to be difficult to explain but I'll try.

I am using UI-router in an angular app and would like t use the following URLS:

/contacts
/contacts/{id}

When you visit the /contacts page it will get a list of contacts from the server and display them. When you go to /contacts/1 it will get the contact 1 record from the server and show it.

My code currently looks like this:

.state('contacts', {
    url: "/contacts",
    templateUrl: "templates/contacts.tpl.html",
    controller: "ContactsCtrl"
})
.state('contacts.contact', {
    url: "/{contactID}",
    templateUrl: "templates/contact.tpl.html",
    controller: "ContactCtrl"
})

So far so good. but when you go to the second URL the parent is also activated so it's going to the server to get the list of contacts, even though they're not displayed, which is a waste.

I could set /contacts to "abstract:true" and use /contacts/list as the first URL, but that's not the URL I want to use and I do need to set a controller on the parent because I do have some logic I want to put in the parent (creating the navigation for that section).

Ideally, when the user hits /contacts I'd like the parent state to activate (to create the navigation) and run a default child state to list the contacts without redirecting to another URL. If the user goes to /contacts/8 then It would still activate the parent state but not the default state so it never goes to the server to get the contacts.

I hope that makes sense. I've not been able to create a plunkr, but the Angular UI guys kindly created one which shows the imperfect solution above.

http://plnkr.co/edit/gmtcE2?p=preview

share|improve this question

1 Answer 1

up vote 13 down vote accepted

I could set /contacts to "abstract:true"

That would be one part of the correct approach. A parent state should not load data that doesn't apply to a child, but your state tree doesn't have to reflect your URL structure exactly. For example:

.state('contacts', {
    abstract: true,
    url: "/contacts",
    /* Various other settings common to both child states */
})
.state('contacts.list', {
    url: "", // Note the empty URL
    templateUrl: "templates/contacts.tpl.html",
    controller: "ContactsCtrl"
})
.state('contacts.item', {
    url: "/{id}",
    templateUrl: "templates/contact.tpl.html",
    controller: "ContactCtrl"
})
share|improve this answer
2  
"Note the empty URL" - Brilliant. I didn't realise that you could still put logic in a controller in an abstract state either. I thought it was just a placeholder. – jonhobbs Mar 9 '14 at 22:26
4  
+1 But this only worked for me when I added template: <ui view /> in the abstract state (or template: <div ui-view /> for those supporting older IE versions). Maybe this used to work on an older version of ui-router but I think this answer should be updated to include what I mentioned (but I'll leave that to you in case I've done something silly that stopped it working like you have it...). – David Spence May 20 '14 at 22:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.