DanTheMan
DanTheMan

Reputation: 556

Angular UI Bootstrap - Collapsing tab content

Using the AngularJS UI Directives for bootstrap, is there any way to collapse the tab content using the tag?

I have several tabs/pills with content, which will start collapsed (hidden). When any of the tabs is activated, the tab content should collapse open, and stay open until a close button is clicked, which will close the collapsable section.

In the controller, I set $scope.isCollapsed to true. Each of the tabs have the ng-click which calls openCollapse(), which sets isCollapsed to false. If I add the collapse="isCollapsed" directive right to the tag, then the tabs disappear too, not just the content.

How can I fix this?

Upvotes: 0

Views: 1065

Answers (1)

DanTheMan
DanTheMan

Reputation: 556

It took some figuring out, but it is possible!

The main problem I had was with scoping issues and transclusion. I hadn't run into transclusion yet (I'm fairly new to Angular), so I'm still wrapping my head around it a bit. I tried a few different ways, and a couple others might have worked, if I understood transclusion a bit better, but in the end, this was the simplest for me, and I got it working.

So basically I had to do 4 main things to get this working.

  1. Open up ui.bootstrap-tpls-0.11.0.js (or whichever version # you're using). Do a search for angular.module("template/tabs/tabset.html". In the <div class=\"tab-content\">\n" tag, add collapse=\"isCollapsed\".
    The tag (and everything in it) gets replaced when compiled, and this is the code that it is replaced with, so this way we can directly put the collapse directive where we need to.

  2. Also in ui.bootstrap-tpls-0.11.0.js, do a search for .directive('tabset'. Inside the link: function(scope, element, attrs) {, add: scope.isCollapsed = scope.$parent.isCollapsed'
    Here we're linking the transcluded scope's isCollapsed to the isCollapsed that is being set in your initial controller (you could also just put initialize isCollapsed in the controller in the next step, instead of just linking it, but I'd already initialized it in my controller and I'd linked it trying to do another method)

  3. Still in ui.bootstrap-tpls-0.11.0.js, do a search for .controller('TabsetController'. Inside this controller, add:

    $scope.$on('openCol', function(event){
        $scope.isCollapsed = false;
    });
    $scope.$on('closeCol', function(event){
        $scope.isCollapsed = true;
    });
    

    What we're doing here is adding event listeners inside the tabset's transcluded scope. What we're going to do at the end, is create an event broadcast. I also added a .$watch(), just so I could see if it was changing:

    $scope.$watch('isCollapsed', function(){
        console.log("isCollapsed has changed, it is now: " + $scope.isCollapsed);
    });
    
  4. Lastly, in the view's controller (or whichever controller contains the .openCollapse() and .closeCollapse()), change your functions from editing this scopes isCollapsed, to:

    $scope.openCollapse = function(){ 
        $rootScope.$broadcast("openCol");
    }
    $scope.closeCollapse = function($event){
        $rootScope.$broadcast("closeCol");
    }
    

    This will broadcast the events that are being listened for in the TabsetController. So now the proper scope of the isCollapsed is being changed, and is reflected in the code. Now watch that lovely tab-content collapsing.

Please let me know if I haven't got my terminology quite right, or if there's something inherently wrong with the way I'm doing it. Or, simply, if there are other ways. Always open to suggestions :)

Upvotes: 0

Related Questions