Multiple "md-tabs" have the "md-active" class at the same time, when I often switch tabs using angular md-selected index

When I switch md-tabs often, Md-tabs switch correctly, but several md-tab-item elements have the class "md-active" at the same time, so I don’t see the active contents of the tab because it overlaps with the right contents of the tab.

According to my words, in the angular material, when we select a tab, angular first deselect the previous tab (hide the previously displayed content on the page) and display the contents of the selected tabs. By performing this process, angular skips the removal of the "md-active" class of the previously active tab.

Here is a fiddle to reproduce the behavior. This random behavior occurs with simultaneous clicks.

Wait 1 minute after clicking jsFiddle

angular.module('firstApplication', ['ngMaterial']).controller('tabController', tabController); function tabController ($scope) { $scope.boards = Array.from(Array(100).keys()); $scope.data = { selectedIndex: 0, secondLocked: true, secondLabel: "2", bottom: false }; $scope.next = function() { $scope.data.selectedIndex = Math.min($scope.data.selectedIndex + 1, 2) ; }; $scope.previous = function() { $scope.data.selectedIndex = Math.max($scope.data.selectedIndex - 1, 0); }; $scope.switch = function() { $scope.activeTabsCounter = $("md-tab-item.md-active").length; } /********* Here i am changing tabs ****8**/ /******** This is strict behaviour where I get the problem but randomly *****/ $scope.switchTabs = function(){ clearInterval(interval); var i = $scope.boards.length - 1; var interval = setInterval(function() { if($scope.activeTabsCounter == 1) { if(i >= 0) $(".md-accent md-tab-item")[i--].click(); $scope.switchTabs(); } else { clearInterval(interval); } }, 100); /********* /Here i am changing tabs ****8**/ } } 
 <link href="https://rawgit.com/angular/bower-material/master/angular-material.css" rel="stylesheet"/> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script> <script src="https://rawgit.com/angular/bower-material/master/angular-material.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-animate.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-aria.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <div ng-app="firstApplication"> <div id="tabContainer" ng-controller="tabController as ctrl" ng-cloak> <div> <br><br> <button ng-click="switchTabs()">Click here to switch tabs</button> <br><br> Current active Tabs: {{activeTabsCounter}} <br> </div> <md-content class="md-padding"> <md-tabs class="md-accent" md-selected="data.selectedIndex" md-align-tabs="{{data.bottom ? 'bottom' : 'top'}}"> <md-tab md-on-select="switch()" id="tab{{board}}" ng-repeat="board in boards"> <canvas id="canvas-{{board}}-1" width="1600" height="900"></canvas> <canvas id="canvas-{{board}}-2" width="1600" height="900"></canvas> <md-tab-label>{{board}}</md-tab-label> <md-tab-body>Item #{{board}} <br/>selectedIndex = {{board}};</md-tab-body> </md-tab> </md-tabs> </md-content> </div> </div> 

I switch tabs in 100 ms, but in our application we also get this problem with a long time interval. We fire the board switch event using the socket.

+6
source share
3 answers

As I understand it, your idea is to change tabs programmatically every X seconds like this ...

First, use angularJs $interval instead of setInterval() (because setInterval () does not care about angular digest).
Secondly, you need to update selectedIndex instead of calling the click() event ...
Lastly, remove the validation of active tabs (I suppose you added for testing)

I updated your jsFiddle

CONTROLLER:

 function tabController($scope, $interval) { $scope.boards = Array.from(Array(100).keys()); $scope.data = { selectedIndex: 0 }; $scope.switchTabs = function() { var size = $scope.boards.length - 1; var interval = $interval(function() { if(size >= 0){ $scope.data.selectedIndex = size--; }else{ $interval.cancel(interval); } }, 750); } } 

HTML:

 <md-tabs class="md-accent" md-selected="data.selectedIndex"> <md-tab ng-repeat="board in boards"> <md-tab-label>{{board}}</md-tab-label> <md-tab-body> Item #{{board}}<br/> selectedIndex = {{board}}; </md-tab-body> </md-tab> </md-tabs> 
+2
source

As OP said in a comment, this was solved by manually deleting the md-active class from all tabs before selecting a new tab (by changing the .selectedIndex data in the code in the question).

For those of us who don't use jQuery in our Angular, JavaScript looks something like this:

 function fixMdTabsActive(tabsId, currentIndex) { var tabs = angular.element(document.getElementById(tabsId)); var elements = tabs.find('md-tab-item'); for (var i = 0; i < elements.length; ++i) { if (i != currentIndex) { angular.element(elements[i]).removeClass('md-active'); } } elements = tabs .find('md-tab-content'); for (var i = 0; i < elements.length; ++i) { if (i != currentIndex) { angular.element(elements[i]).removeClass('md-active'); } } } 
0
source

I partially solved this problem in my code by adding md-active="$index == data.selectedIndex" to my md-tab definition. Theoretically, this is not necessary, but when I built my tabs, I would set data.selectedIndex to the last tab, and the first and last would be active. After adding this line, it basically worked. I had one race condition that made me remove the md-active class, as described in the OP comment, and another answer (community).

0
source

Source: https://habr.com/ru/post/1015402/


All Articles