ui-router中的多态视图

时间:2014-05-20 10:59:54

标签: angularjs angular-ui-router

我们说我有一个person数据对象,可以是不同类型的人:

{
  name: 'Clyde',
  gender: 'male'
},
{
  name: 'Jean',
  gender: 'female'
}

所以,我有一个处理这个问题的视图状态,但我希望其中的细节不同......

国家

$stateProvider.state('person', {
  url: '/person/:id',
  templateUrl: 'person.html',
  controller: 'PersonController',
  resolve: {
    personInstance: function($stateParams, dataModel) {
      return dataModel.getPerson($stateParams.id);
    }
  }
};

查看     人:{{personInstance.name}}       

好的,所以我有我的状态,但是我希望子状态代表我不同的多态视图:

$stateProvider
  .state('person.male', {
    templateUrl: 'person-male.html',
    controller: 'PersonMaleController'
  })
  .state('person.female', {
    templateUrl: 'person-female.html',
    controller: 'PersonFemaleController'
  });

冷却。但是......我该如何过渡到这个州?在数据结算之前,我不知道这是哪种类型的人。我是否需要在父母的onEnter回调中执行此操作?

onEnter: function($state, $stateParams, personInstance) {
  if(personInstance.gender === 'male') {
    $state.go('person.male', $stateParams);
  } else if(personInstance.gender === 'female') {
    $state.go('person.female', $stateParams);
  }
}

这似乎是合理的,但这样做会触发父状态,这会导致onEnter事件,从而导致转换,这将永远发生。一般来说,这感觉有点偏,但我无法找到更好的方法来做到这一点。感觉有更好的方式。

修改 顺便说一下,我已尝试将其保留为单个状态,并在ng-switch中执行person.html并使用ng-include包含模板,该模板明确设置控制器。但是那个孩子控制器并没有得到personInstance传入的引用。这比我的反应更糟糕,但这是我尝试过的。

1 个答案:

答案 0 :(得分:0)

您的解决方案很有效,除了您必须在PersonController中进行重定向,这不是由子状态继承的。从父控制器重定向似乎也很合适,父控制器可以包含所有子类型共有的任何逻辑。

<!DOCTYPE html>
<html ng-app="app">
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="angular.js"></script>
    <script src="angular-ui-router.js"></script>
</head>
<body>
<h1>Polymorphic States with ui-router</h1>
<div ui-view></div>

<script>

    var app = angular.module('app', ["ui.router"]);

    app.config(function($stateProvider, $urlRouterProvider){
        $urlRouterProvider.otherwise("/person/1");
        $stateProvider
                .state('person', {
                    url: '/person/:id',
                    //templateUrl: 'person.html',
                    template: '<h2>Generic Person Template</h2><ui-view></ui-view>',
                    controller: 'PersonController',
                    resolve: {
                        personInstance: function($stateParams, dataModel) {
                            return dataModel.getPerson($stateParams.id);
                        }
                    }
                })
                .state('person.male', {
                    template: '<h3>This is a male person view</h3>',
                    controller: 'PersonMaleController'
                })
                .state('person.female', {
                    template: '<h3>This is a female person view</h3>',
                    controller: 'PersonFemaleController'
                })
        ;
    });
    app.controller('PersonController', function ($state, personInstance) {
        // Do stuff here relevant to both genders.

        if(personInstance.gender === 'male') {
            $state.go('person.male');
        } else if(personInstance.gender === 'female') {
            $state.go('person.female');
        }
    });

    app.controller('PersonMaleController', function ($state) {
    });
    app.controller('PersonFemaleController', function ($state) {
    });
    app.factory('dataModel', function($q){
        return{
            getPerson: getPerson
        };
        function getPerson(id){
            var people = [
                {
                    id: 1,
                    name: 'Clyde',
                    gender: 'male'
                },
                {
                    id: 2,
                    name: 'Jean',
                    gender: 'female'
                }];
            var person = {};
            for(var i = 0; i < people.length; i++){
                if (people[i].id == parseInt(id)) {
                    person = people[i];
                }
            }
            return $q.when(person);
        }
    });
</script>
</body>
</html>