如果我有这个代码:
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
使用 AngularJS、angular-ui 和 Twitter Bootstrap,是否可以让手风琴在打开时调用一些动作?我知道我不能简单地添加ng-click
,因为它在“编译”为 HTML 以打开/折叠组后已经使用。
如果我有这个代码:
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
使用 AngularJS、angular-ui 和 Twitter Bootstrap,是否可以让手风琴在打开时调用一些动作?我知道我不能简单地添加ng-click
,因为它在“编译”为 HTML 以打开/折叠组后已经使用。
手风琴组还允许手风琴标题指令而不是将其作为属性提供。您可以使用它,然后通过 ng-click 将您的标题包装在另一个标签中。
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
<accordion-heading>
<span ng-click="opened(group, $index)">{{group.content}}</span>
</accordion-heading>
</accordion-group>
这是基于pkozlowski.opensource解决方案的解决方案。您可以使用动态定义的 Property,
而不是在集合的每个项目上添加$watch。在这里,你可以将绑定IsOpened的财产组的是开放的属性。
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.IsOpened">
{{group.content}}
</accordion-group>
因此,您可以在控制器中的每个集合项上动态添加IsOpened属性:
$scope.groups.forEach(function(item) {
var isOpened = false;
Object.defineProperty(item, "IsOpened", {
get: function() {
return isOpened;
},
set: function(newValue) {
isOpened = newValue;
if (isOpened) {
console.log(item); // do something...
}
}
});
});
使用属性而不是手表对性能更好。
is-open
手风琴组上有一个指向可绑定表达式的属性。当给定的手风琴组打开时,您可以观察这个表达式并执行一些逻辑。使用此技术,您可以将标记更改为:
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
{{group.content}}
</accordion-group>
以便您可以在控制器中准备所需的监视表达式:
$scope.$watch('groups[0].open', function(isOpen){
if (isOpen) {
console.log('First group was opened');
}
});
虽然上述工作在实践中使用可能有点麻烦所以如果你觉得这可以改进在https://github.com/angular-ui/bootstrap 中打开一个问题
这是一个受 kjv 回答启发的解决方案,它可以轻松跟踪打开的手风琴元素。我发现很难ng-click
处理手风琴标题,尽管在<span>
标签中围绕元素并添加 ng-click 效果很好。
我遇到的另一个问题是,虽然accordion
元素是以编程方式添加到页面的,但内容却没有。当我尝试使用{{path}}
链接到$scope
变量的Angular 指令(即)加载内容时,我会被击中undefined
,因此使用了波纹管方法,该方法使用div
嵌入的 ID 填充手风琴内容。
控制器:
//initialise the open state to false
$scope.routeDescriptors[index].openState == false
function opened(index)
{
//we need to track what state the accordion is in
if ($scope.routeDescriptors[index].openState == true){ //close an accordion
$scope.routeDescriptors[index].openState == false
} else { //open an accordion
//if the user clicks on another accordion element
//then the open element will be closed, so this will handle it
if (typeof $scope.previousAccordionIndex !== 'undefined') {
$scope.routeDescriptors[$scope.previousAccordionIndex].openState = false;
}
$scope.previousAccordionIndex = index;
$scope.routeDescriptors[index].openState = true;
}
function populateDiv(id)
{
for (var x = 0; x < $scope.routeDescriptors.length; x++)
{
$("#_x" + x).html($scope.routeDescriptors[x]);
}
}
HTML:
<div ng-hide="hideDescriptions" class="ng-hide" id="accordionrouteinfo" ng-click="populateDiv()">
<accordion>
<accordion-group ng-repeat="path in routeDescriptors track by $index">
<accordion-heading>
<span ng-click="opened($index)">route {{$index}}</span>
</accordion-heading>
<!-- Notice these divs are given an ID which corresponds to it's index-->
<div id="_x{{$index}}"></div>
</accordion-group>
</accordion>
</div>
我使用了一个关联数组来创建打开状态和模型对象之间的关系。
HTML是:
<div ng-controller="CaseController as controller">
<accordion close-others="controller.model.closeOthers">
<accordion-group ng-repeat="topic in controller.model.topics track by topic.id" is-open="controller.model.opened[topic.id]">
<accordion-heading>
<h4 class="panel-title clearfix" ng-click="controller.expand(topic)">
<span class="pull-left">{{topic.title}}</span>
<span class="pull-right">Updated: {{topic.updatedDate}}</span>
</h4>
</accordion-heading>
<div class="panel-body">
<div class="btn-group margin-top-10">
<button type="button" class="btn btn-default" ng-click="controller.createComment(topic)">Add Comment<i class="fa fa-plus"></i></button>
</div>
<div class="btn-group margin-top-10">
<button type="button" class="btn btn-default" ng-click="controller.editTopic(topic)">Edit Topic<i class="fa fa-pencil-square-o"></i></button>
</div>
<h4>Topic Description</h4>
<p><strong>{{topic.description}}</strong></p>
<ul class="list-group">
<li class="list-group-item" ng-repeat="comment in topic.comments track by comment.id">
<h5>Comment by: {{comment.author}}<span class="pull-right">Updated: <span class="commentDate">{{comment.updatedDate}}</span> | <span class="commentTime">{{comment.updatedTime}}</span></span></h5>
<p>{{comment.comment}}</p>
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs" ng-click="controller.editComment(topic, comment)">Edit <i class="fa fa-pencil-square-o"></i></button>
<button type="button" class="btn btn-default btn-xs" ng-click="controller.deleteComment(comment)">Delete <i class="fa fa-trash-o"></i></button>
</div>
</li>
</ul>
</div>
</accordion-group>
</accordion>
控制器代码段是:
self.model = {
closeOthers : false,
opened : new Array(),
topics : undefined
};
“主题”填充在 AJAX 调用中。将“打开”状态与从服务器更新的模型对象分开意味着状态在刷新时得以保留。
我还声明了控制器 ng-controller="CaseController as controller"