ViciousKitten ViciousKitten - 1 year ago 48
AngularJS Question

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:

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!


Answer Source

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: