问题描述:

I recently migrated from ngRoute to ui-router. I have a page that has 2 sections.

Right section displays current item details,

Left section shows similar items to current item.

Once user clicks a similar item from left list, right section will reload with clicked item id and left section will stay same.

To keep left section still on user item navigations, i defined left section as an abstract state and right section as it's child state. (you cant view similar items if you arent looking to an item).

Left section (listview) is parent and contains a ui-view in HTML to embed item details.

To load similar items on page open, i need to know which item is being loaded by my child state. But i cant define same url for both abstract state and it's child state.

i tried to resolve $stateParams in abstract state with no chance.

my state configuration is below

app.config(['$stateProvider', function ($stateProvider) {

$stateProvider

.state('item', {

//url: '/items/:itemName/:itemID'

url: '/items',

abstract: true,

templateUrl: 'Scripts/app/item/ItemListTemplate.html',

controller: 'ItemListController as itemList'

}).state('item.itemDetails', {

url: '/:itemName/:itemID',

templateUrl: 'Scripts/app/item/ItemDetailTemplate.html',

controller: 'ItemDetailController as itemDetail'

});

how can i access itemID from my abstract state (from ItemListController)?

网友答案:

i solved the problem using angular scope variable. parent contains an ui-view to show child state contents. so child and parent state share same scope therefore i can notify parent about selected item id and parent can update it's view.

parent state has a scope function like this

$scope.notifySelectedItem = function(selectedItemID){};

and child state can call this function from it's scope

$scope.notifySelectedItem($stateParams.itemID);
网友答案:

I would model this as a single state with two named views. The subject of your state is a single item and related data, so your state should probably revolve around that. You have described two views, one which shows the item details, and another which shows other things, but the primary subject is still the one item.

 $stateProvider
    .state('item', {
        url: '/item/:itemID',
        views: {
          detail: {
            templateUrl: 'Scripts/app/item/ItemDetailTemplate.html',
            controller: 'ItemDetailController as itemDetail'
          }, related: {
            templateUrl: 'Scripts/app/item/ItemListTemplate.html',
            controller: 'ItemListController as itemList'
          }
        }           
    });

In your parent view, add two named ui-views, where the views defined above will plug into:

<div ui-view="related"></div>
<div ui-view="detail"></div>

Now, you can enhance this using resolves to preload the data before the controller is invoked:

 $stateProvider
    .state('item', {
        url: '/item/:itemID',
        resolve: { 
          item: function($http, $stateParams) {
            return $http.get('/item/' + $stateParams.itemID); 
          },
          related: function($http, $stateParams) { 
            return $http.get('/item/' + $stateParams.itemID + "/related");
          },
        },
        views: {
          detail: {
            templateUrl: 'Scripts/app/item/ItemDetailTemplate.html',
            controller: 'ItemDetailController as itemDetail'
          }, related: {
            templateUrl: 'Scripts/app/item/ItemListTemplate.html',
            controller: 'ItemListController as itemList'
          }
        }           
    });

app.controller("ItemListController", function($scope, related) { $scope.related = related.data; });
app.controller("ItemDetailController", function($scope, item) { $scope.item = item.data; });
相关阅读:
Top