Javascript 以角度处理手风琴的打开/折叠事件
如果我有此代码:Javascript 以角度处理手风琴的打开/折叠事件,javascript,twitter-bootstrap,angularjs,angular-ui,Javascript,Twitter Bootstrap,Angularjs,Angular Ui,如果我有此代码: <accordion-group heading="{{group.title}}" ng-repeat="group in groups"> {{group.content}} </accordion-group> {{group.content} 使用AngularJS、AngularUI和Twitter引导,打开手风琴时是否可以调用一些动作?我知道我不能简单地添加ng click,因为在将其“编译”为HTML以打开/折叠组后,它已
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
{{group.content}
使用AngularJS、AngularUI和Twitter引导,打开手风琴时是否可以调用一些动作?我知道我不能简单地添加
ng click
,因为在将其“编译”为HTML以打开/折叠组后,它已经被使用。在accordion组上有is open
属性,它指向一个可绑定的表达式。当给定的手风琴组打开时,您可以观察这个表达式并执行一些逻辑。使用此技术,您可以将标记更改为:
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
{{group.content}}
</accordion-group>
尽管上述方法可行,但在实践中使用起来可能有点麻烦,因此如果您觉得这可以改进,请在手风琴组中打开一个问题,也允许使用手风琴标题指令,而不是将其作为属性提供。您可以使用它,然后使用ng单击将标题包装到另一个标记中
<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>
accordion-controller.js
MyApp.Controllers
.controller('AccordionCtrl', ['$scope', function ($scope) {
$scope.groups = [
{
title: "Dynamic Group Header - 1",
content: "Dynamic Group Body - 1",
open: false
},
{
title: "Dynamic Group Header - 2",
content: "Dynamic Group Body - 2",
open: false
},
{
title: "Dynamic Group Header - 3",
content: "Dynamic Group Body - 3",
open: false
}
];
/**
* Open panel method
* @param idx {Number} - Array index
*/
$scope.openPanel = function (idx) {
if (!$scope.groups[idx].open) {
console.log("Opened group with idx: " + idx);
$scope.groups[idx].open = true;
}
};
/**
* Close panel method
* @param idx {Number} - Array index
*/
$scope.closePanel = function (idx) {
if ($scope.groups[idx].open) {
console.log("Closed group with idx: " + idx);
$scope.groups[idx].open = false;
}
};
}]);
index.html
<div ng-controller="AccordionCtrl">
<accordion>
<accordion-group ng-repeat="group in groups" is-open="group.open">
<button ng-click="closePanel($index)">Close me</button>
{{group.content}}
</accordion-group>
<button ng-click="openPanel(0)">Set 1</button>
<button ng-click="openPanel(1)">Set 2</button>
<button ng-click="openPanel(2)">Set 3</button>
</accordion>
</div>
关上我
{{group.content}
第1组
第2组
第三组
以下是一个受kjv答案启发的解决方案,它可以轻松跟踪打开的手风琴元素。我发现很难让ng click
处理手风琴标题,尽管在
标记中包围元素并将ng click添加到该标题中效果很好
我遇到的另一个问题是,虽然accordion
元素是通过编程方式添加到页面中的,但内容不是这样的。当我尝试使用链接到$scope
变量的角度指令(即{{path}
)加载内容时,我会被未定义的击中,因此使用了下面的方法,该方法使用嵌入其中的IDdiv
填充手风琴内容
控制器:
//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]);
}
}
<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>
//将打开状态初始化为false
$scope.routeDescriptors[index].openState==false
功能已打开(索引)
{
//我们需要追踪手风琴的状态
如果($scope.routedDescriptors[index].openState==true){//关闭手风琴
$scope.routeDescriptors[index].openState==false
}否则{//打开手风琴
//如果用户单击另一个手风琴元素
//然后打开的元素将被关闭,因此这将处理它
if(typeof$scope.previousAccordinationIndex!=“未定义”){
$scope.RoutedDescriptors[$scope.PreviousAccordinationIndex].openState=false;
}
$scope.previousAccordionIndex=索引;
$scope.routeDescriptors[index].openState=true;
}
函数populateDiv(id)
{
对于(变量x=0;x<$scope.routedDescriptors.length;x++)
{
$(“#ux”+x).html($scope.routedDescriptors[x]);
}
}
HTML:
//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]);
}
}
<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>
路由{{$index}
我使用关联数组在打开状态和模型对象之间创建关系
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>
“主题”是在AJAX调用中填充的。将“打开”状态与从服务器更新的模型对象分离意味着该状态在刷新过程中保留
我还声明了带有ng controller=“CaseController as controller”的控制器这是一个基于pkozlowski.opensource解决方案的解决方案。
您可以使用动态定义的属性,而不是在集合的每个项目上添加$watch。在这里,您可以将组的IsOpen属性绑定到is open属性
{{group.content}
因此,您可以在控制器中集合的每个项目上动态添加IsoPend属性:
$scope.groups.forEach(函数(项){
var-isOpened=false;
Object.defineProperty(项“IsOpen”{
get:function(){
返回等厚线;
},
set:函数(newValue){
等间距=新值;
如果(等参线){
console.log(item);//做点什么。。。
}
}
});
});
使用属性代替手表对性能更有利。您可以使用角度指令:
html
我在那里的设置有一些特点(我使用Django,因此使用了“{%verbatim%}”标记),但是该方法应该可以工作。我可以让观看更通用吗?比如-这样我就不必编写”组[0].open'
为每一行打开。我不知道预先会有多少行…@Michal我担心当前的实现并不简单。你可以像这样设置一个深度监视:但我不推荐这样做。…@pkozlowski.opensource我们有带手风琴标题的is open
选项吗@opensource-谢谢你的例子。这当然是可行的,但你们打算正式地将打开/关闭事件添加到Accordion控件吗?原始的Bootstrap可折叠控件有一个。我不敢相信这不容易做到。这完全是垃圾。当然,开发人员会想为一个开放组观看一个Accordion,当它出现时anges。这很简单。是的,手风琴标题允许我们在单击时打开或关闭面板,但这不是一个暴露如何从其他触发器打开面板的示例。这是我能找到的最干净的解决方案。谢谢,喝杯啤酒吧!这很好,唯一的问题是手风琴标题占据了整行,而打开的函数只会当你直接点击textcool way时,你会被调用!+1请注意不要在第一次尝试时放弃,通过使用alert或某个console.log测试点击。它不起作用,请使用你现有的功能进行尝试
<div uib-accordion-group is-open="property.display_detail" ng-repeat="property in properties">
<div uib-accordion-heading ng-click="property.display_detail = ! property.display_detail">
some heading text
</div>
<!-- here is the accordion body -->
<div ng-init="i=$index"> <!-- I keep track of the index of ng-repeat -->
<!-- and I call a custom directive -->
<mydirective mydirective_model="properties" mydirective_index="{% verbatim ng %}{{ i }}{% endverbatim ng %}">
here is the body
</mydirective>
</div>
</div>
app.directive("mydirective", function() {
return {
restrict: "EAC",
link: function(scope, element, attrs) {
/* note that ng converts everything to camelCase */
var model = attrs["mydirectiveModel"];
var index = attrs["mydirectiveIndex"];
var watched_name = model + "[" + index + "].display_detail"
scope.$watch(watched_name, function(is_displayed) {
if (is_displayed) {
alert("you opened something");
}
else {
alert("you closed something");
}
});
}
}
});