角UI路由器实例子控制器多次 [英] Angular ui-router instantiates the child controller multiple times

查看:100
本文介绍了角UI路由器实例子控制器多次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<大骨节病> SWEET DEMO

我有型材,其中每个简档可以是在摘要或在详细视图的列表。只有一个配置文件可以具有在任何时间的详细视图。

I have a list of profiles, where each profile can be either in a summary or in a detailed view. Only one profile can have a detailed view at any time.

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的路由器配置

$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'
      }
    }
  });

问题我有:


  • 在<大骨节病>更多点击按钮时, ProfileDetailsCtrl 被实例化的3倍。我怎么能初始化它,只有正在扩展模板?

  • 是我利用UI路由器灵活性正确,或有实现这个更好的办法? (注意::当轮廓扩大,应该体现在URL(使它可收藏))

  • When the More button is clicked, ProfileDetailsCtrl is instantiated 3 times. How could I instantiate it only for profile that is extended?
  • Am I utilizing the ui-router flexibility properly, or there is a better way to implement this? (Note: When profile is expanded, it should be reflected in the URL (to make it bookmarkable))

<大骨节病> 操场这里

推荐答案

在下面的评论讨论后,有一个为不同的溶液基本的(必填)的概念:

Extend with detail Replace

After discussion in comments below, there is a different solution for the basic (required) concept:

里面一个列表 - 如何更换一排的(上单击)的,更多的细节 - UI路由器

Inside a list - How to replace a row (on-click), with more details - using ui-router?

即。让我们先从这样的:

I.e. let's start with this:


  • <大骨节病>更多1 基本INFO1

  • <大骨节病>更多2 基本INFO2 //点击这里更多

  • <大骨节病>更多3 基本INFO2

  • More 1 basic info1
  • More 2 basic info2 // click more here
  • More 3 basic info2

得到这个当<大骨节病>更多2 被点击的(ANG越来越回来,如果<大骨节病>小于2 点击NEXT)

getting this when More 2 is clicked (ang getting back if Less 2 is clicked next)


  • <大骨节病>更多1 基本INFO1

  • <大骨节病>小于2 加载UI路由器状态机非常详细的信息...

  • <大骨节病>更多3 基本INFO2

  • More 1 basic info1
  • Less 2 very detailed information loaded with ui-router state machine...
  • More 3 basic info2

这将是解决办法:

1)列表视图模板,将有 NG-如果,检查是否有一定的 详细信息 信息,或不:

1) The list view template, would have ng-if, checking if there is some detail info, or not:

<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-点击只是我们使用内置的 UI-SREF 使用相对路径DEF UI-SREF =配置文件({配置文件ID:profile.id})。 - 这将调用子状态的简介

A few fancy parts to mention: instead of some ng-click we just do use the built in ui-sref with a relative path def ui-sref=".profile({profileId:profile.id})" - That will call the child state profile.

一旦孩子被加载,我们就可以拿回通过重新调用父 UI-SREF =。(哇......)

Once child is loaded, we can just get back by re-calling the parent ui-sref="." (wow...)

2)我们的 详细信息 的状态会做两件事情。

2) Our detail state will be doing two things


  1. 将ID加载细节// GetById称为服务器上

  2. 休假//恢复列表中,因为它是清理

  1. load the detail by ID // GetById called on a Server
  2. cleanup on leave // Restoring the list as it was

//找到父集合的配置文件
无功配置= _.find($ scope.profiles,{ID:$ stateParams.profileId});

// find a profile from parent collection var profile = _.find($scope.profiles, {id : $stateParams.profileId});

$ HTTP
    获得(detail.json)// getById
    。然后(功能(响应){

$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;

});

//清理 - 删除细节
  VAR清理=功能(){
     删除profile.detail;
  }
  $ $范围上($消灭,清理);

// cleanup - remove the details var cleanup = function(){ delete profile.detail; } $scope.$on("$destroy", cleanup);

有几件事情提:我们勾上 $范围事件消灭。这将被解雇,一旦我们回到父。而这也正是我们清理所有的 UI路由器详细过程中所做的脚印的地方的状态往返...

A few things to mention: we hook on the $scope event "destroy". This will be fired, once we go back to the parent. And that's the place where we clean all the foot prints made during the ui-router detail state round-trip...

3)详细视图

有是没有的。无,监守我们不需要的模板。好吧,其实我们仍然需要视图锚,哪里是详细的状态放在...并在 DetailController 被称为!

There is NONE. None, becuase we do not need a template. Well in fact we still need the view anchor, where is the detail state placed... and the DetailController is called!

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

因此​​必须有某个地方是视图锚父:

so there must be the view anchor somewhere in the parent:

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

工作code 例如

Working code example:

看看一个该解决方案这里 ... 应该明确

Take a look a that solution here... it should be clear

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

控制器的实例化多次,多次被它的视图的注入页面。而你要做注入视图的 3倍

The controller is instantiated as many times, as many times is its view injected into the page. And you do inject the view 3 times.

下面是轮廓的源

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

下面,我们确实创造了锚/使用相同的用户界面视图名称目标:

Here we do create anchors/targets with the same ui-view name:

<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'
      }
    }
  });

解决方法:这不应该发生。我们不应该使用一个用户界面视图=的viewName莫雷不止一次。这是工作。但它不是我们能正确管理......简单地从中继移动目标...

Solution: this should not happen. We should not use one ui-view="viewName" moret than once. It is working. but it is not what we can correctly manage... simply move the targets from repeater...

扩展这里我更新了 plunker ,我做了profiles.html像这样

EXTEND here I updated the plunker, I made the profiles.html like this

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

和我迭代里面FO摘要:

And I do iterate inside fo the summary:

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

所以,现在,每个用户界面视图只有一次 ...看到,在行动的这里

So now, each ui-view is there only once... see that in action here

这篇关于角UI路由器实例子控制器多次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆