Search code examples
angularjscheckboxbootstrap-5accordion

Unexpected Checkbox Behavior in Bootstrap 5 Accordion


I have a selection of checkbox items that I want to put into a Bootstrap 5 accordian element. The checkbox items work fine in the open (checking the boxes adds items to an array; unchecking them removes items from the array), but when I place them in an accordian element, they do not work (checking the boxes does nothing; unchecking them adds items to the array).

Here's the code by itself.

<form class = "list">
  <div class="form-check" ng-repeat="x in people_list">
    <a id="{{x.initial}}"></a>
    <input class="form-check-input" type="checkbox" id={{x.id}} ng-click="clickPeople(x.id, x.names)" ng-checked="checkall" ng-model="x.Selected">
    <label class="form-check-label" for={{x.id}}>{{x.names}} ({{x.tag_link_count}})</label>
  </div>
</form>             

Here's the code inserted into an accordian element.

<div class="accordion" id="accordionExample">
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
        Select Tags to Search For
      </button>
    </h2>
    <div id="collapseOne" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
      <div class="accordion-body">
        <form class = "list">
          <div class="form-check" ng-repeat="x in tags">
        <a id="{{x.initial}}"></a>
          <input class="form-check-input" type="checkbox" id={{x.id}} ng-click="clickPeople(x.id, x.names)" ng-checked="checkall" ng-model="x.Selected">
          <label class="form-check-label" for={{x.id}}>{{x.names}} ({{x.tag_link_count}})</label>
      </div>
    </form>                       
      </div>
    </div>
  </div>
</div>

This CodePen contains both working and non-working examples of my checkboxes (my JSFiddle account seems to be having issues).

I have seen references in answers to similar issues that talk about stopping click event propagation, but I can't wrap my mind about how to fix my problems using the examples I've found. Any help/guidance would be appreciated.

Cheers, Bill


Solution

  • These are the list of changes made:

    1. The click event, I am passing the entire object x and maintaining the selected property in the name Selected, then using this I am validating the item if it's checked or not.
    2. The click event has a typo where you are looking for name property, but in the object it is defined as names, so I changed the JS code to use names.
    3. Finally I removed the code outside accordion which is causing some weird scrolling, there should be only one element with a unique ID.

    Please find below a working example:

    var app = angular.module("myApp", []);
    var nonYearList = [];
    var yearList = [];
    var peopleList = [];
    var eventList = [];
    var holidayList = [];
    var otherList = [];
    var tagNameList = [];
    app.controller("myCtrl", function($scope) {
      $scope.tags = [{
          "id": 2,
          "names": "Clarence Gansemer",
          "type": "2",
          "tag_link_count": "1",
          "initial": "C"
        },
        {
          "id": 6,
          "names": "Dave Anderson",
          "type": "2",
          "tag_link_count": "1",
          "initial": "D"
        },
        {
          "id": 3,
          "names": "Dorothy Strong, Dorothy Gansemer",
          "type": "2",
          "tag_link_count": "2",
          "initial": "D"
        }
      ]
      $scope.clickPeople = function(item) {
        item.Selected = !item.Selected;
        if (item.Selected) {
          tagNameList.push(item.names)
          $scope.tag_names = tagNameList;
        } else {
          var spot = nonYearList.indexOf(item.id);
          if (spot != -1) {
            nonYearList.splice(spot, 1);
          }
          var spot2 = peopleList.indexOf(item.id);
          if (spot2 != -1) {
            peopleList.splice(spot2, 1);
          }
          var spot3 = tagNameList.indexOf(item.names);
          if (spot3 != -1) {
            tagNameList.splice(spot3, 1);
          }
    
        }
    
      }
    
    });
    <html>
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>RBT - Tag Search</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    </head>
    
    <body ng-app="myApp" ng-controller="myCtrl">
      <br><br>
      <h4>Checkboxes do not work inside accordion (checked names are not added to Selected Names list (unless they are checked and then un-checked))</h4>
      <div class="accordion" id="accordionExample">
        <div class="accordion-item">
          <h2 class="accordion-header">
            <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
              Select Tags to Search For
            </button>
          </h2>
          <div id="collapseOne" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
            <div class="accordion-body">
              <form class="list">
                <div class="form-check" ng-repeat="x in tags">
                  <a id="{{x.initial}}"></a>
                  <input class="form-check-input" type="checkbox" id={{x.id}} ng-click="clickPeople(x)" ng-checked="x.Selected" ng-model="x.Selected">
                  <label class="form-check-label" for={{x.id}}>{{x.names}} ({{x.tag_link_count}})</label>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
      <div>
        <br>
        <h4>Selected Names</h4>
        <div ng-repeat="name in tag_names"><span style="margin-left:25px;margin-right:5px" class="badge rounded-pill bg-primary"> </span>&ensp;{{name.replace('Unknown','Unknown Year')}}</div>
      </div>