Search code examples
javascriptangularjsscopetabsusing-directives

Angular JS: How to open a tab from outside it's directive


I have followed a tutorial on creating tabs in angular, please see a simplified plunkr of my actual code here: https://embed.plnkr.co/ysWI0pSeBVGEi8Iok2mY/

My tabs are working great and i can toggle between them, however I now want to set tabs to active from outside of the directive (see the buttons in the plunkr).

What is the best way to do this?

I am very new to angular (first project) so would really appreciate any help!

Thanks


Solution

  • The way to control things in Angular is through the model. So, you add a variable in the outer scope that holds the selected tab index and pass it to the tabset:

    <tabset selected-index="selectedTabIndex">
    

    And the buttons set this variable:

    <button class="open-tab-1" ng-click="selectedTabIndex = 0">Open Tab 1</button>
    <button class="open-tab-2" ng-click="selectedTabIndex = 1">Open Tab 2</button>
    

    (I am using an ad-hoc variable, selectedTabIndex and I am manipulating directly through ng-click. This is for the sake of simplicity for this example; I would rather place the variable in a controller and manipulate it through controller functions.)

    Now the tabset has to understand the new attribute. Add it to the scope definition (since you are using Angular 1.5, preferably a 1-way binding):

    scope: {
      selectedIndex: '<'
    },
    

    And the code to handle changes in the selectedIndex, i.e. activate the tab at the given index, deactivate all others; I am using Object.defineProperty to reduce watches:

      var _selectedIndex = 0;
      Object.defineProperty(this, 'selectedIndex', {
        get: function() {
          return _selectedIndex;
        },
        set: function(val) {
          if( typeof val === 'number' ) {
            _selectedIndex = val;
            for( var i=0; i < self.tabs.length; i++ ) {
              self.tabs[i].active = (i === val);
            }
          }
        }
      });
    

    This could be written with a watch too:

      $scope.$watch('tabset.selectedIndex', function(newval, oldval) {
        if( newval !== oldval ) {
          for( var i=0; i < self.tabs.length; i++ ) {
            self.tabs[i].active = (i === newval);
          }
        }
      });
    

    A plunk: http://plnkr.co/edit/5LVLZ3zJPBNRddpsUs20?p=preview