角UI路由器实例子控制器多次 [英] Angular ui-router instantiates the child controller multiple times
问题描述
<大骨节病> 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
- 将ID加载细节// GetById称为服务器上
-
休假//恢复列表中,因为它是清理
- load the detail by ID // GetById called on a Server
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屋!