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

Mis*_*hko 9 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>
Run Code Online (Sandbox Code Playgroud)

型材summary.html

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

简介 - 汇总controller.js

$scope.showProfileDetails = function(profileId) {
  $state.go('profiles.profile', { profileId: profileId });
};
Run Code Online (Sandbox Code Playgroud)

profile-details .html

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

型材细节,controller.js

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

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'
      }
    }
  });
Run Code Online (Sandbox Code Playgroud)

我有的问题:

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

PLAYGROUND HERE

Rad*_*ler 6

扩展详细信息替换

在下面的评论中讨论后,基本(必需)概念有一个不同的解决方案:

在列表中 - 如何使用更多详细信息替换行(点击) - 使用 ui-router

即,让我们从这开始:

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

More 2单击时获取此信息(如果Less 2单击下一步则返回)

  • More 1 基本信息1
  • Less 2 加载ui-router状态机的非常详细的信息......
  • More 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>
Run Code Online (Sandbox Code Playgroud)

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

一旦孩子被加载,我们可以通过重新呼叫父母回来ui-sref="." (哇...)

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

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

    //从父集合中查找配置文件var profile = _.find($ scope.profiles,{id:$ stateParams.profileId});

    $ http .get("detail.json")// getById .then(function(response){

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

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

有几点需要注意:我们挂钩$scope事件"破坏".一旦我们回到父母那里,这将被解雇.这就是我们清理在ui-router 详细状态往返期间制作的所有足迹的地方......

3)详细视图

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

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

所以在父级的某处必须有视图锚点:

<div ui-view="profile-details"></div>
Run Code Online (Sandbox Code Playgroud)

工作代码示例:

看看一个该解决方案在这里 ...... 应该清楚

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

原始部分答案

控制器被实例化多次,多次为它的视图插入到页面.你确实注入了3次视图.

这是配置文件的来源

$scope.profiles = [
    { id: '100', name: 'Misko Hevery' },
    { id: '101', name: 'Igor Minar' },
    { id: '102', name: 'Vojta Jina' },
];
Run Code Online (Sandbox Code Playgroud)

在这里,我们创建具有相同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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

// NO repeater here
<div ui-view="profile-summary"></div>
<div ui-view="profile-details"></div>
Run Code Online (Sandbox Code Playgroud)

我会在摘要中进行迭代:

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

所以,现在,每ui-view一次 ......看到,在行动这里