gstyle
gstyle

Reputation: 33

I want to make accordion in ng-repeat loop using angularjs only with no ui.bootstrap and no jquery

I tried using the code given below. This code is not collapsing others. It simply leave other panels open.I want to close other panels on clicking of the current panel. Any help will be appreciated without using jQuery and ui.bootstrap

<div id="accordion" class="panel-group">
    <div ng-repeat="item in awesomeThings" >
        <div class="panel panel-default">
            <div class="panel-heading">
                 <h4 class="panel-title">
                     <a data-toggle="collapse" data-parent="#accordion"
                        href="#collapse{{$index+1}}"
                        ng-click="print($event)" class="nothing" >click</a>
                 </h4>
            </div>
            <div id="collapse{{$index+1}}" class="panel-collapse collapse ">
                <div class="panel-body">
               {{item.item}}
                </div>
            </div>
        </div>
    </div>
</div>

and the controller part in which I tried adding the collapsed class to all and then adding the in class to the current clicked item and also removing the collapsed class from the current item

$scope.print= function($event){
   var el= angular.element(document.querySelector('.nothing'));
   console.log(el);
   el.addClass('collapsed');
   angular.element($event.target).removeClass('collapsed');
   angular.element($event.target).addClass('in');
}

Upvotes: 2

Views: 1428

Answers (1)

Mosh Feu
Mosh Feu

Reputation: 29307

First, document.querySelector returns only the first match but you want to get them all. querySelectorAll won't do the job either because you target the <a /> tags which change their classes will do nothing.

If any, you can change the classes of the .collapse elements - remove in and add collapsed.

<!DOCTYPE html>
<html>

<head>
  <title></title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
  <script type="text/javascript">
    var app = angular.module('ngapp', []);
    app.controller('mainctrl', function($scope) {
      $scope.awesomeThings = [{
        item: 'heoj'
      }, {
        item: 'nniothing'
      }, {
        item: 'skgjs'
      }];
      $scope.print = function($event) {
        var el = angular.element('.panel-collapse');
        el.removeClass('in').addClass('collapsed');
        angular.element($event.target).removeClass('collapsed');
        angular.element($event.target).addClass('in');
      }
    })
  </script>
</head>

<body ng-app="ngapp" ng-controller="mainctrl">
  <div id="accordion" class="panel-group">
    <div ng-repeat="item in awesomeThings">
      <div class="panel panel-default">
        <div class="panel-heading">
          <h4 class="panel-title">
            <a data-toggle="collapse" data-parent="#accordion" href="#collapse{{$index+1}}" ng-click="print($event)" class="nothing">click</a>
          </h4>
        </div>
        <div id="collapse{{$index+1}}" class="panel-collapse collapse ">
          <div class="panel-body">
            {{item.item}}
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

https://jsbin.com/momuniz/edit?html,output


But this will hide the expanded panels without animation because changing the classes is not enough, it should be with timing so the collapse will be smooth.

To fix it, we need bootstrap to do the collapse and there is an API for that: collapse ().

So instead of remove and add classes by yourself, let bootstrap to do it with

el.collapse('hide')

Live example

<!DOCTYPE html>
<html>

<head>
  <title></title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
  <script type="text/javascript">
    var app = angular.module('ngapp', []);
    app.controller('mainctrl', function($scope) {
      $scope.awesomeThings = [{
        item: 'heoj'
      }, {
        item: 'nniothing'
      }, {
        item: 'skgjs'
      }];
      $scope.print = function($event) {
        angular.element('.panel-collapse').collapse('hide');
      }
    })
  </script>
</head>

<body ng-app="ngapp" ng-controller="mainctrl">
  <div id="accordion" class="panel-group">
    <div ng-repeat="item in awesomeThings">
      <div class="panel panel-default">
        <div class="panel-heading">
          <h4 class="panel-title">
            <a data-toggle="collapse" data-parent="#accordion" href="#collapse{{$index+1}}" ng-click="print($event)" class="nothing">click</a>
          </h4>
        </div>
        <div id="collapse{{$index+1}}" class="panel-collapse collapse ">
          <div class="panel-body">
            {{item.item}}
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

https://jsbin.com/nigumad/edit?html,output

By the way, you don't need querySelector/All when you use angular.element because you can pass the selector directly to angular.element - angular.element('.nothing')

Upvotes: 1

Related Questions