Angular ui-router to accomplish a conditional view

2019-02-04 20:09发布

I am asking a similar question to this question: UI Router conditional ui views?, but my situation is a little more complex and I cannot seem to get the provided answer to work.

Basically, I have a url that can be rendered two very different ways, depending on the type of entity that the url points to.

Here is what I am currently trying

    $stateProvider
        .state('home', {
            url : '/{id}',
            resolve: {
                entity: function($stateParams, RestService) {
                    return RestService.getEntity($stateParams.id);
                }
            },
            template: 'Home Template <ui-view></ui-view>',
            onEnter: function($state, entity) {
                if (entity.Type == 'first') {
                    $state.transitionTo('home.first');
                } else {
                    $state.transitionTo('home.second');
                }
            }
        })
        .state('home.first', {
            url: '',
            templateUrl: 'first.html',
            controller: 'FirstController'
        })
        .state('home.second', {
            url: '',
            templateUrl: 'second.html',
            controller: 'SecondController'
        });

I set up a Resolve to fetch the actual entity from a restful service. Every thing seems to be working until I actually get to the transitionTo based on the type.

The transition seems to work, except the resolve re-fires and the getEntity fails because the id is null.

I've tried to send the id to the transitionTo calls, but then it still tries to do a second resolve, meaning the entity is fetched from the rest service twice.

What seems to be happening is that in the onEnter handler, the state hasn't actually changed yet, so when the transition happens, it thinks it is transitioning to a whole new state rather than to a child state. This is further evidenced because when I remove the entity. from the state name in the transitionTo, it believes the current state is root, rather than home. This also prevents me from using 'go' instead of transitionTo.

Any ideas?

4条回答
劳资没心,怎么记你
2楼-- · 2019-02-04 20:19

I ended up making the home controller a sibling of first and second, rather than a parent, and then had the controller of home do a $state.go to first or second depending on the results of the resolve.

查看更多
祖国的老花朵
3楼-- · 2019-02-04 20:20

The templateUrl can be a function as well so you check the type and return a different view and define the controller in the view rather than as part of the state configuration. You cannot inject parameters to templateUrl so you might have to use templateProvider.

$stateProvider.state('home', {
  templateProvider: ['$stateParams', 'restService' , function ($stateParams, restService) {
    restService.getEntity($stateParams.id).then(function(entity) {
        if (entity.Type == 'first') {
              return '<div ng-include="first.html"></div>;
        } else {
              return '<div ng-include="second.html"></div>';
        }
    });
  }]
})
查看更多
叼着烟拽天下
4楼-- · 2019-02-04 20:35

You can also do the following :

$stateProvider
        .state('home', {
            url : '/{id}',
            resolve: {
                entity: function($stateParams, RestService) {
                    return RestService.getEntity($stateParams.id);
                }
            },
            template: 'Home Template <ui-view></ui-view>',
            onEnter: function($state, entity) {
                if (entity.Type == 'first') {
                    $timeout(function() {
                            $state.go('home.first');
                        }, 0);
                } else {
                    $timeout(function() {
                            $state.go('home.second');
                        }, 0);
                }
            }
        })
        .state('home.first', {
            url: '',
            templateUrl: 'first.html',
            controller: 'FirstController'
        })
        .state('home.second', {
            url: '',
            templateUrl: 'second.html',
            controller: 'SecondController'
        });
查看更多
Explosion°爆炸
5楼-- · 2019-02-04 20:35

Use verified code for conditional view in ui-route

$stateProvider.state('dashboard.home', {
        url: '/dashboard',
        controller: 'MainCtrl',
       // templateUrl: $rootScope.active_admin_template,
        templateProvider: ['$stateParams', '$templateRequest','$rootScope', function ($stateParams, templateRequest,$rootScope) {
          var templateUrl ='';
          if ($rootScope.current_user.role == 'MANAGER'){
            templateUrl ='views/manager_portal/dashboard.html';
          }else{
            templateUrl ='views/dashboard/home.html';
          }
          return templateRequest(templateUrl);
        }]
      });
查看更多
登录 后发表回答