angular ui-bootstrap手风琴如何实现自定义行为:默认全部关闭,点击一个accordion-group标题时,打开所有其他
angular ui-bootstrap accordion how to achieve customized behavior: default all close, when clicking one accordion-group heading, open all others
我正在使用 ui-bootstrap 手风琴。我有一个手风琴里面的手风琴。
在第一个手风琴下'Category',我有另一个手风琴,有3个手风琴组。它们默认关闭。我想要这样的行为:当你点击一个手风琴组标题时(比如 'fruit'),如果所有的手风琴组都关闭了,那么它会打开它们......但是如果有任何组是打开的(比如任何一个'fruit', 'meat', and vegetable' is open when user is clicking), then when you click, it will toggle the clicked accordion-group.你可以在这里查看 plunker:
http://plnkr.co/edit/UcETfOVh8RwMX40mOCVv?p=preview
我的 html 和 angular 代码如下:
<!DOCTYPE html>
<html ng-app="plunker">
<body ng-controller="AccordionDemoCtrl">
<accordion >
<accordion-group>
<accordion-heading> Category</accordion-heading>
<accordion ng-repeat="(category, items) in categories" close-others="oneAtATime" is-open="true">
<accordion-group >
<accordion-heading ><div>{{category}}</div></accordion-heading>
<div ng-repeat="item in items.data">{{item}}</div>
</accordion-group>
</accordion>
</accordion-group>
</accordion>
</body>
</html>
angular.module('plunker', ['ui.bootstrap']);
function AccordionDemoCtrl($scope) {
$scope.categories = {
fruit: {
data: {
apple: 3,
orange: 5,
lemon: 6
},
toggled: false
},
vegetable: {
data: {
lettuce: 1,
broccoli: 5,
spinach: 4
},
toggled: false
},
meat: {
data: {
chicken: 3,
beef: 6,
lamb: 8
},
toggled: false
}
};
}
我怎样才能实现这种行为?我在另一个 plunker 有工作进展:
http://plnkr.co/edit/9eTfpn81g57Dk4FtVSlA?p=preview
我在手风琴中探索了 'is-open' 属性,我试图引用 $parent,但没有产生我想要的行为。
WABBIT0111
您可能想要使用属性 is-open=ctrlVar
。
这样您就可以用 ng-click=action to change ctrlVar state
设置它,然后将它们切换回原来的位置。
正如 bobleujr 所提到的 is-open
应该可以。但是代码有点棘手,我不确定是否有更简单的解决方案。
问题是我添加 'toggleAll' 检查的 ng-click
在切换点击的手风琴后被调用。
所以我必须跟踪以前的手风琴状态以确保我们必须切换所有手风琴。我通过遍历所有 accodions 状态并计算它是否打开来做到这一点。
那我稍后再看看previousCount == 0
和currentCount==1
是否需要全部打开
我不喜欢为行为做两个 for 循环,但我认为这是唯一的方法。
如果它不会用 ng-click
切换状态,那就更容易了。但我不知道怎么办。我试图禁用手风琴指令的 is-open
切换,但那没有用。
手风琴指令的 Decorating 可能会有所帮助,然后您可以在切换之前添加检查。但这可能并不那么容易。
请在更新后的 plunkr.
中查看下面或此处的演示
// Code goes here
angular.module('plunker', ['ui.bootstrap'])
.controller('AccordionDemoCtrl', AccordionDemoCtrl);
function AccordionDemoCtrl($scope) {
var prevOpenCount = 0;
$scope.toggle = function(index) {
var openCount = 0,
openAll = false;
// check how many accordions are open
for( var i=0; i < $scope.openState.length; i++ ){
if ($scope.openState[i] === true) {
openCount++;
}
}
if ( openCount === 1 && prevOpenCount === 0) { // open all
for( var i=0; i < $scope.openState.length; i++ ){
$scope.openState[i] = true;
}
}
//console.log(index, $scope.openState, openCount, prevOpenCount);
prevOpenCount = openCount;
};
$scope.categories = {
fruit: {
data: {
apple: 3,
orange: 5,
lemon: 6
},
toggled: false
},
vegetable: {
data: {
lettuce: 1,
broccoli: 5,
spinach: 4
},
toggled: false
},
meat: {
data: {
chicken: 3,
beef: 6,
lamb: 8
},
toggled: false
}
};
$scope.openState = new Array(Object.keys($scope.categories).length);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.js"></script>
<!--<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.9.0.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.3/ui-bootstrap-tpls.js"></script>
<!--<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
--><script src="script.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<div ng-app="plunker" ng-controller="AccordionDemoCtrl">
<accordion>
<accordion-group>
<accordion-heading> Category</accordion-heading>
<accordion ng-repeat="(category, items) in categories" close-others="oneAtATime">
<accordion-group ng-click="toggle($index, $event)" is-open="openState[$index]">
<accordion-heading ><div><!--{{openState}}-->{{category}}</div></accordion-heading>
<div ng-repeat="item in items.data">{{item}}</div>
</accordion-group>
</accordion>
</accordion-group>
</accordion>
</div>
我正在使用 ui-bootstrap 手风琴。我有一个手风琴里面的手风琴。
在第一个手风琴下'Category',我有另一个手风琴,有3个手风琴组。它们默认关闭。我想要这样的行为:当你点击一个手风琴组标题时(比如 'fruit'),如果所有的手风琴组都关闭了,那么它会打开它们......但是如果有任何组是打开的(比如任何一个'fruit', 'meat', and vegetable' is open when user is clicking), then when you click, it will toggle the clicked accordion-group.你可以在这里查看 plunker:
http://plnkr.co/edit/UcETfOVh8RwMX40mOCVv?p=preview
我的 html 和 angular 代码如下:
<!DOCTYPE html>
<html ng-app="plunker">
<body ng-controller="AccordionDemoCtrl">
<accordion >
<accordion-group>
<accordion-heading> Category</accordion-heading>
<accordion ng-repeat="(category, items) in categories" close-others="oneAtATime" is-open="true">
<accordion-group >
<accordion-heading ><div>{{category}}</div></accordion-heading>
<div ng-repeat="item in items.data">{{item}}</div>
</accordion-group>
</accordion>
</accordion-group>
</accordion>
</body>
</html>
angular.module('plunker', ['ui.bootstrap']);
function AccordionDemoCtrl($scope) {
$scope.categories = {
fruit: {
data: {
apple: 3,
orange: 5,
lemon: 6
},
toggled: false
},
vegetable: {
data: {
lettuce: 1,
broccoli: 5,
spinach: 4
},
toggled: false
},
meat: {
data: {
chicken: 3,
beef: 6,
lamb: 8
},
toggled: false
}
};
}
我怎样才能实现这种行为?我在另一个 plunker 有工作进展: http://plnkr.co/edit/9eTfpn81g57Dk4FtVSlA?p=preview 我在手风琴中探索了 'is-open' 属性,我试图引用 $parent,但没有产生我想要的行为。
WABBIT0111
您可能想要使用属性 is-open=ctrlVar
。
这样您就可以用 ng-click=action to change ctrlVar state
设置它,然后将它们切换回原来的位置。
正如 bobleujr 所提到的 is-open
应该可以。但是代码有点棘手,我不确定是否有更简单的解决方案。
问题是我添加 'toggleAll' 检查的 ng-click
在切换点击的手风琴后被调用。
所以我必须跟踪以前的手风琴状态以确保我们必须切换所有手风琴。我通过遍历所有 accodions 状态并计算它是否打开来做到这一点。
那我稍后再看看previousCount == 0
和currentCount==1
是否需要全部打开
我不喜欢为行为做两个 for 循环,但我认为这是唯一的方法。
如果它不会用 ng-click
切换状态,那就更容易了。但我不知道怎么办。我试图禁用手风琴指令的 is-open
切换,但那没有用。
Decorating 可能会有所帮助,然后您可以在切换之前添加检查。但这可能并不那么容易。
请在更新后的 plunkr.
中查看下面或此处的演示// Code goes here
angular.module('plunker', ['ui.bootstrap'])
.controller('AccordionDemoCtrl', AccordionDemoCtrl);
function AccordionDemoCtrl($scope) {
var prevOpenCount = 0;
$scope.toggle = function(index) {
var openCount = 0,
openAll = false;
// check how many accordions are open
for( var i=0; i < $scope.openState.length; i++ ){
if ($scope.openState[i] === true) {
openCount++;
}
}
if ( openCount === 1 && prevOpenCount === 0) { // open all
for( var i=0; i < $scope.openState.length; i++ ){
$scope.openState[i] = true;
}
}
//console.log(index, $scope.openState, openCount, prevOpenCount);
prevOpenCount = openCount;
};
$scope.categories = {
fruit: {
data: {
apple: 3,
orange: 5,
lemon: 6
},
toggled: false
},
vegetable: {
data: {
lettuce: 1,
broccoli: 5,
spinach: 4
},
toggled: false
},
meat: {
data: {
chicken: 3,
beef: 6,
lamb: 8
},
toggled: false
}
};
$scope.openState = new Array(Object.keys($scope.categories).length);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.js"></script>
<!--<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.9.0.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.3/ui-bootstrap-tpls.js"></script>
<!--<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
--><script src="script.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<div ng-app="plunker" ng-controller="AccordionDemoCtrl">
<accordion>
<accordion-group>
<accordion-heading> Category</accordion-heading>
<accordion ng-repeat="(category, items) in categories" close-others="oneAtATime">
<accordion-group ng-click="toggle($index, $event)" is-open="openState[$index]">
<accordion-heading ><div><!--{{openState}}-->{{category}}</div></accordion-heading>
<div ng-repeat="item in items.data">{{item}}</div>
</accordion-group>
</accordion>
</accordion-group>
</accordion>
</div>