Question

I'm trying to make a bootstrap accordion with an internal button that will collapse the current accordion segment and open the next one, this for some reason is not working.

HTML:

<div ng-controller="AccordionDemoCtrl">  
    <accordion>
       <accordion-group id="firstpanel" heading="Static Header 1"  is-open="status.isFirstOpen">
          <span id="span1">This content is straight in the template.</span><br> 
          <button id="nextpanel">Next</button>
       </accordion-group>
       <accordion-group heading="Static Header 2">
          <span id="span1">This content is straight in the template.</span>
       </accordion-group>
    </accordion>
</div>

JAVASCRIPT:

angular.module('plunker', ['ui.bootstrap']);
function AccordionDemoCtrl($scope) {
  $scope.status = {
    isFirstOpen: true,
    isFirstDisabled: false
  };

  $("#nextpanel").on("click", function() {   
   $(firstpanel).click();
  });
}

I have made a plunker example here: Plunker

Was it helpful?

Solution

You cannot use jquery selectors inside controller constructors. DOM elements like #nextpanel are not even in the DOM tree at that phase, so $("#nextpanel") is essentially an empty array.

I suggest you forget about jquery alltogether. The only case for jquery, is maybe when you need to use a plugin you are already familiar with (like a calendar). In any case, jquery code (the one with the $()) should stricktly reside in the link function of the directive that wraps the plugin.

The MVC way, is to have a "model" (JS object) drive the UI. Angular will do its magic to keep the two synced.

A model that stores which accordion is open could simply be an array of booleans:

$scope.status = [true, false, false, false];

Opening the next accordion is simply finding which one is opened, and set to true the next one (or wrap around to the first one).

$scope.next = function() {
    var indx = $scope.status.indexOf(true);
    $scope.status[(++indx) % $scope.status.length] = true;
};

The accordion component will make sure that only one of them is true at any given time.

Now, your template is something like:

<accordion>

    <accordion-group heading="Static Header 1"  is-open="status[0]">
      <span>This content is straight in the template.</span><br>
      <button ng-click="next()">Next</button>
    </accordion-group>

    <accordion-group heading="Static Header 2"  is-open="status[1]">
      <span>This content is straight in the template.</span><br>
      <button ng-click="next()">Next</button>
    </accordion-group>

    <accordion-group heading="Static Header 3"  is-open="status[2]">
      <span>This content is straight in the template.</span><br>
      <button ng-click="next()">Next</button>
    </accordion-group>

    <accordion-group heading="Static Header 4" is-open="status[3]">
      <span>This content is straight in the template.</span><br>
      <button ng-click="next()">Start over</button>
    </accordion-group>

</accordion>

Here is the fixed plunker.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top