angular ui-bootstrap手风琴如何实现自定义行为:默认全部关闭,当点击一个手风琴组标题时,打开所有其他

时间:2015-08-28 21:40:38

标签: angularjs accordion angular-ui-bootstrap

我正在使用ui-bootstrap手风琴。手风琴里面有手风琴。 enter image description here

在第一支手风琴'类别'下,我有另一支手风琴,有3个手风琴组。它们默认是关闭的。我想要这样的行为:当你点击一个手风琴小组的标题(说'水果'),如果所有的手风琴小组都关闭了,那么它将全部打开...但是如果有任何小组是开放的(比如说如果用户点击时有任何“水果”,“肉类”和“蔬菜”打开,那么当您点击时,它将切换点击的手风琴组。你可以在这里看看这个plunker:

http://plnkr.co/edit/UcETfOVh8RwMX40mOCVv?p=preview

我的html和角度代码如下:

<!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 我已经和'开放'一起探索过了。手风琴中的属性,我试图引用$ parent,而不是产生我想要的行为。

2 个答案:

答案 0 :(得分:3)

正如bobleujr is-open所提到的那样。但代码有点棘手,我不确定是否有更简单的解决方案。

问题在于,我添加'toggleAll'检查的ng-click是在点击所点击的手风琴之后调用的。 因此,我必须跟踪之前的手风琴状态,以确保我们必须切换所有手风琴。我这样做是通过循环遍历所有的比赛状态并计算它是否打开。

然后我可以稍后检查previousCount == 0currentCount==1是否需要打开所有内容。

我不喜欢为行为做两个for循环,但我认为这是唯一的方法。

如果它不会用ng-click切换状态,那么它会更容易。但我不知道怎么做。我试图禁用手风琴指令的is-open切换,但这不起作用。

手风琴指令的

Decorating可以帮助您在toggeling之前添加支票。但那可能并不那么容易。

请查看下面的演示或更新后的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>

答案 1 :(得分:1)

WABBIT0111

您可能想要使用属性is-open=ctrlVar

这样您就可以使用ng-click=action to change ctrlVar state进行设置,然后将其切换回原始位置。