Angular ui-router多次实例化子控制器

时间:2014-07-23 02:57:57

标签: angularjs angular-ui-router

SWEET DEMO

我有一个配置文件列表,其中每个配置文件可以是摘要或详细视图。任何时候只有一个配置文件可以有详细的视图。

profiles.html

<div ng-repeat="profile in profiles">
  <div ui-view="profile-summary"></div>
  <div ui-view="profile-details"></div>
</div>

个人资料-summary.html

<div ng-if="$state.params.profileId !== profile.id">
  {{ profile.name }}
  <button ng-click="showProfileDetails(profile.id)">More</button>
</div>

个人资料 - 摘要-controller.js

$scope.showProfileDetails = function(profileId) {
  $state.go('profiles.profile', { profileId: profileId });
};

个人资料详情.html

<div ng-if="$state.params.profileId === profile.id">
  Detailed profile of {{ profile.name }}
  <button ng-click="hideProfileDetails()">Less</button>
</div>

个人资料-细节-controller.js

$scope.hideProfileDetails = function() {
  $state.go('profiles.profile', { profileId: null });
};

ui-router配置

$stateProvider
  .state('profiles', {
    url: '/profiles?keywords',
    views: {
      'profiles': {
        templateUrl: 'profiles.html',
        controller: 'ProfilesCtrl'
      },
      'profile-summary@profiles': {
        templateUrl: 'profile-summary.html',
        controller: 'ProfileSummaryCtrl'
      }
    }
  })
  .state('profiles.profile', {
    url: '/:profileId',
    views: {
      'profile-details': {
        templateUrl: 'profile-details.html',
        controller: 'ProfileDetailsCtrl'
      }
    }
  });

我的问题:

  • 单击 More 按钮时,ProfileDetailsCtrl将被实例化3次。我怎样才能为扩展的配置文件实例化它?
  • 我是否正确使用ui-router灵活性,或者有更好的方法来实现它? (注意:展开个人资料时,应将其反映在网址中(以使其可收藏))

PLAYGROUND HERE

1 个答案:

答案 0 :(得分:6)

详细扩展替换

在下面的评论中讨论后,基本(必需)概念有different solution

  

在列表中 - 如何使用> ui-router更多详细信

即。让我们从这开始:

  • 更多1 基本信息1
  • 更多2 基本信息2 //点击此处
  • 更多3 基本信息2

点击更多2 (如果下次点击 Less 2 ,则返回

  • 更多1 基本信息1
  • 少2 非常详细的信息加载ui-router状态机......
  • 更多3 基本信息2

这将是解决方案:

1)列表视图模板将ng-if,检查是否有 detail 信息:

<div ng-repeat="profile in profiles">

  <div ng-if="!profile.detail">
    <button ui-sref=".profile({profileId:profile.id})">More</button>
    {{ profile.name }}
  </div>

  <div ng-if="profile.detail">        
    <button ui-sref=".">Less</button>
    {{ profile.detail | json }}
  </div>

</div>

要提到一些奇特的部分:我们只使用内置ng-click并使用相对路径def ui-sref而不是某些ui-sref=".profile({profileId:profile.id})" - 这将调用子状态简介

加载子项后,我们可以通过重新调用父ui-sref="." (哇...)

来取回

2)我们的 detail 州将会做两件事

  1. 通过在服务器上调用的ID // GetById加载详细信息
  2. 休假时清理//按原样恢复列表

    //从父系列中查找个人资料 var profile = _.find($ scope.profiles,{id:$ stateParams.profileId});

    $ HTTP     .get(&#34; detail.json&#34;)// getById     。然后(功能(响应){

      // would contain just a detail for id... here we filter
      var detail = _.find(response.data, {id : $stateParams.profileId});
    
      // assign the detail
      profile.detail = detail;
    
    });
    

    //清理 - 删除详细信息   var cleanup = function(){      删除profile.detail;   }   $ scope。$ on(&#34; $ destroy&#34;,cleanup);

  3. 有几点值得一提:我们挂钩$scope事件&#34;销毁&#34;。一旦我们回到父母那里,这将被解雇。这就是我们清理ui-router 详细州往返期间所有足迹的地方......

    3)详细视图

    没有。没有,因为我们不需要模板。实际上我们仍然需要视图锚点,其中放置了详细状态......并且调用了 DetailController

      .state('profiles.profile', {
        url: '/:profileId',
        views: {
          'profile-details': {   // NO template
            controller: 'ProfileDetailsCtrl'
          }
        }
      });
    

    所以父视图中必须有视图锚点

    <div ui-view="profile-details"></div>
    

    工作代码example

    看看那个解决方案here ... 它应该是明确的

    (以下是为什么多次触发控制器的答案的原始部分)

    答案的原始部分

    控制器被多次实例化,因为它的视图被注入页面很多次。并且您确实将视图注入了3次

    以下是个人资料的来源

    $scope.profiles = [
        { id: '100', name: 'Misko Hevery' },
        { id: '101', name: 'Igor Minar' },
        { id: '102', name: 'Vojta Jina' },
    ];
    

    在这里,我们使用相同的ui-view名称创建锚点/目标:

    <div ng-repeat="profile in profiles">   // for each profile in our array
      <div ui-view="profile-summary"></div>
      <div ui-view="profile-details"></div> // we inject this view named profile-details
    </div>
    

    最后,我们要求将我们的观点注入这些(3)父/子视图目标

    .state('profiles.profile', {
        url: '/:profileId',
        views: {
          'profile-details': {                 // the parent view-target is there 3 times
            templateUrl: 'profile-details.html',
            controller: 'ProfileDetailsCtrl'
          }
        }
      });
    

    解决方案:这不应该发生。我们不应该只使用一次ui-view="viewName"。这是工作。但这不是我们能正确管理的......只需从转发器中移动目标......

    EXTEND在这里我更新了plunker,我像这样制作了profiles.html

    // NO repeater here
    <div ui-view="profile-summary"></div>
    <div ui-view="profile-details"></div>
    

    我在摘要中进行了迭代:

    <div ng-repeat="profile in profiles">
      {{ profile.name }}
      <button ng-click="showProfileDetails(profile.id)">More</button>
    </div>
    

    现在,每个ui-view只有一次 ...请参阅here