Search code examples
javascriptangularjsangularjs-scopeangular-material

Change index of AngularJS md-tabs have no effect at all


In my Angular app, I have a md-tabs whose md-selected directive is binded to a property in my controller. I'd like to change the current tab to the one whose index is set by a function called by ng-click somewhere else in my template.

I did it this way:

<div ng-controller="TrackingCtrl" layout-fill>
   <md-content ng-if="isSmart" layout-fill>
      <md-tabs md-selected="selectedIndex" layout-fill>
         <md-tab>.........</md-tab>
         <md-tab>.........</md-tab>
         <md-tab>.........</md-tab>
         <md-tab>
            <md-tab-label>{{ 'tracking.positions.TITLE' | translate }}</md-tab-label>
            <md-tab-body>
                <md-tab-content layout-fill flex>
                    <button ng-click="map.panTo(getPosition());displayMap();"></button>
            </md-tab-body>
         </md-tab>
    </md-tabs>
 </md-content>
</div>

In my controller I have :

  $scope.selectedIndex = 0;
  $scope.displayMap = function() {
      $scope.selectedIndex = 1;
  };

But it has no effect at all when I click my button which calls displayMap();

I've inspected the problem:

  • When I set $scope.selectedIndex = 1; in my controller, the default tab is the one whose index is 1. OK
  • When I set md-selected="1" in my template, the default tab is the one whose index is 1. OK
  • When I set a breakpoint in my code, and when I click my button, displayMap() is called, and $scope.selectedIndex = 1; is executed. OK

It seems everything works fine... except the tab doesn't change.

I'm running Angular Material 1.0.2

I even used $apply to force update (no effect) :

  $scope.selectedIndex = 0;
  $scope.displayMap = function () {
      $timeout(function () {
          if (!$scope.$$phase) {
              $scope.$apply(function () {
                  $scope.selectedIndex = 1;
              });
          }
      });
  };

Solution

  • I solved my problem which was certainly caused by a scope issue. I simply used the controller as syntax, and declared every previous scope data with:

    var self = this;
    self.selectedIndex = 0;
    self.displayMap = function (){
       self.selectedIndex = 1;
    };
    

    and my markup:

    <div ng-controller="TrackingCtrl as tracking" layout-fill>
      <md-content ng-if="tracking.isSmart" layout-fill>
        <md-tabs md-selected="tracking.selectedIndex" layout-fill>
           <md-tab>.........</md-tab>
           <md-tab>.........</md-tab>
           <md-tab>.........</md-tab>
           <md-tab>
              <md-tab-label>{{ 'tracking.positions.TITLE' | translate }}</md-tab-label>
              <md-tab-body>
                 <md-tab-content layout-fill flex>
                    <button ng-click="tracking.displayMap();"></button>
                 </md-tab-content>
              </md-tab-body>
           </md-tab>
      </md-tabs>
     </md-content>
    </div>
    

    Works perfect now. I guess my ng-if was modifying my scope or so.