Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular UI-router default state on same URL

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

like image 863
jonhobbs Avatar asked Mar 08 '14 23:03

jonhobbs


1 Answers

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"
})
like image 108
Nate Abele Avatar answered Sep 25 '22 19:09

Nate Abele