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 == 0currentCount==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>