How to call different functions from different controllers on the click of each tab in angular ui tabs?

863 Views Asked by At

I'm trying to call different functions from different controllers on the click of each tab using angular-ui tabs directive.

HTML

<tabset>
  <tab heading="Reports" ng-controller="ReportsController" ng-click="fetchReports()" id="tab1">
    <div> Reports </div>
  </tab>
  <tab heading="Sales" ng-controller="SalesController" ng-click="fetchSales()" id="tab2">
    <div> Sales </div>
  </tab>
</tabset>

I'm getting error like this

Multiple directives [ngController, tab] asking for new/isolated scope

Requirement

I have 5-6 tabs in a page. The page should not load the data of each tab at once. It should only load data for a tab once that tab is being clicked.

Solution

I have a solution to wrap the tabset directive with a parent controller such that i can have then broadcast events from the ParentController to call the functions from the respective Child controllers.

<div ng-controller='ParentController'>
  <tabset>
    <tab heading="Reports" id="tab1">
      <div ng-controller="ChildOneController"> Reports </div>
    </tab>
    <tab heading="Sales" id="tab2">
      <div ng-controller="ChildTwoController"> Sales </div>
    </tab>
  </tabset>
</div>

Problem:

But sadly i have too many pages with tabs in my application and i dont think broadcasting events for each tab from ParentController to ChildController is a good idea. i need to know what should be a good solution for it ?

2

There are 2 best solutions below

2
Gavin Gregory On

You could use controller as syntax:

<div ng-controller="ReportsController as reports">
  <div ng-controller="SalesController as sales">
    <tabset>
      <tab heading="Reports" ng-click="reports.fetchReports()" id="tab1">
        <div> Reports </div>
      </tab>
      <tab heading="Sales" ng-click="sales.fetchSales()" id="tab2">
        <div> Sales </div>
      </tab>
    </tabset>
  </div>
</div>

Here is an example of what the controller would look like:

(function(){

  angular
    .module('app')
    .controller('ReportsController', [
      ReportsController
    ]);

  function ReportsController() {
    var vm = this;

    vm.fetchReports = function () {
      // fetch the reports! 
    };
  }

})();

Source: John Papa's angular style guide recommends using the controller as syntax over $scope, see style guide.

4
Alvaro Silvino On

In your case,

you should create an directive:

In this way you can use an loop in order to create multiples directives with multiples controllers.

(function() {

    angular
      .module('app')
      .diretive('directiveTab', function() {
          return {
            restrict: 'AE',
            template: " <div> Reports </div>"//you can use templateUrl as well
            scope: {},
            controller: ['$scope',
              function($scope) {
                $scope.function1 = function(pane) {
                  
                };
              }
            ],
          };
        }
      })
the directive will behave like controller and you can manipulate the content of each tab

<div ng-controller='ParentController'>
  <tabset>
    <tab heading="Reports" id="tab1">
      <directive-tab>
    </tab>
  </tabset>
</div>