1

Here is my $stateProvider configuration:

.state('itemDetail', {
    abstract: true,
    url: '/itemDetail/general/:itemid',
    controller: 'ItemDetailsController',
    templateUrl: './partials/itemDetails.html'
})
.state('itemDetail.general', {
    url: "",
    controller: 'ItemDetailsController',
    templateUrl: "./partials/itemDetails.General.html"
})
.state('itemDetail.file', {
    url: "/file/:itemid",
    controller: 'ItemDetailsController',
    templateUrl: "./partials/itemDetails.File.html"
})

The user can look at item using #/itemDetail/general/96045 and can click the link to look at file attachments. Now it is work but URL for files now is #/itemDetail/general/96045/file/96045.

Is it possible to have URL for files as #/itemDetail/file/96045?

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
ceth
  • 44,198
  • 62
  • 180
  • 289
  • Setting `abstract` to `true` in your `itemDetail` state will always prepend any children states with the `url` defined in that state (i.e. `/itemDetail/general/`). You could instead have `url` in the `itemDetail` state set to `/itemDetail`, and `url` in the `itemDetail.general` state set to `/general/:itemId`. If doing this, you will obviously have to adjust your template markup links. – miqh Nov 20 '15 at 07:21
  • Yes, it works. But in this case it works if I go to the view using `ui-sref`, but the `$stateParams` is undefined if I open `itemDetails/general/100` direct in the browser. In this (unworking) case the ItemController called only once (for one view) – ceth Nov 20 '15 at 07:38

2 Answers2

2

Well, I would go with one parent and only one child state. There is a working plunker

This will be the new one child state itemDetail.type:

.state('itemDetail', {
  abstract: true,
  url: '/itemDetail',
  controller: 'ItemDetailsController',
  templateUrl: 'partials/itemDetails.html'
})
.state('itemDetail.type', {
  url: "/:type/:itemid",
  controller: 'ItemDetailsController',
  templateProvider: ['$stateParams', '$templateRequest', 
    function($stateParams, $templateRequest) {
      var url = "partials/itemDetails.General.html";
      if($stateParams.type === "file"){
          url = "partials/itemDetails.File.html"  
      }
      return $templateRequest(url);
  }],
})

We are using here $stateParams.type to decide which template to load (and also $templateRequest to profit from angula built in caching)

And this will be the calling html:

<a ui-sref="itemDetail.type({type:'general', itemid:1})">
<a ui-sref="itemDetail.type({type:'file', itemid:22})">

The url will now look as expected

check it here

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thanks, but if I undertood correctly it will be work only if all states have one (and the same) Controller. But it is not my case (in general). – ceth Nov 20 '15 at 07:26
  • 1
    Surprisingly we can use the same trick for controller - http://stackoverflow.com/a/30260604/1679310 ... coool ;) *(I just used your snippet.. but UI-Router built in features are ... bloody fantastic)* – Radim Köhler Nov 20 '15 at 07:29
  • Thanks. But I have one more question :). I need to have itemid in `partials/itemDetails.html`. If I set `url: '/itemDetail'` for `itemDetail` state - I will not have this variable in my controller for this view. What is the good way to solve this problem ? – ceth Nov 20 '15 at 19:28
  • Great to see that progress ;) Because we are on the right track with this approach... Well we can move that params into parent state.. it is not an issue: http://plnkr.co/edit/542Rc0kRaXfVkBswAJpC?p=preview BUT It wil mean that even parent will be reloaded when any params is changed ;) good luck with UI-Router sir – Radim Köhler Nov 20 '15 at 19:31
0

Yes it can be you need to give state as

.state('itemDetail.file', {
        url: '/{itemId}',
        controller: 'ItemDetailsController',
        templateUrl: 'partials/itemDetails.html'
    })
Soni Pandey
  • 514
  • 5
  • 16