Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 39d0b36

Browse files
matskoIgorMinar
authored andcommitted
fix($animate): ensure hidden elements with ngShow/ngHide stay hidden during animations
Prior to this fix if an element that contained ng-show or ng-hide was in its hidden state then any other animation run on the same element would cause the animation to appear despite the element itself already being hidden. This patch ensures that NO animations are visible even if the element is set as hidden. Closes #9103 Closes #9493
1 parent 035ffb8 commit 39d0b36

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

css/angular.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
44
.ng-cloak, .x-ng-cloak,
5-
.ng-hide:not(.ng-animate) {
5+
.ng-hide:not(.ng-hide-animate) {
66
display: none !important;
77
}
88

src/ng/directive/ngShowHide.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
var NG_HIDE_CLASS = 'ng-hide';
4+
var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
35
/**
46
* @ngdoc directive
57
* @name ngShow
@@ -161,7 +163,11 @@ var ngShowDirective = ['$animate', function($animate) {
161163
multiElement: true,
162164
link: function(scope, element, attr) {
163165
scope.$watch(attr.ngShow, function ngShowWatchAction(value){
164-
$animate[value ? 'removeClass' : 'addClass'](element, 'ng-hide');
166+
// we're adding a temporary, animation-specific class for ng-hide since this way
167+
// we can control when the element is actually displayed on screen without having
168+
// to have a global/greedy CSS selector that breaks when other animations are run.
169+
// Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
170+
$animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, NG_HIDE_IN_PROGRESS_CLASS);
165171
});
166172
}
167173
};
@@ -316,7 +322,9 @@ var ngHideDirective = ['$animate', function($animate) {
316322
multiElement: true,
317323
link: function(scope, element, attr) {
318324
scope.$watch(attr.ngHide, function ngHideWatchAction(value){
319-
$animate[value ? 'addClass' : 'removeClass'](element, 'ng-hide');
325+
// The comment inside of the ngShowDirective explains why we add and
326+
// remove a temporary class for the show/hide animation
327+
$animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, NG_HIDE_IN_PROGRESS_CLASS);
320328
});
321329
}
322330
};

test/ng/directive/ngShowHideSpec.js

+44
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,28 @@ describe('ngShow / ngHide animations', function() {
156156
expect(item.element.text()).toBe('data');
157157
expect(item.element).toBeHidden();
158158
}));
159+
160+
it('should apply the temporary `.ng-hide-animate` class to the element',
161+
inject(function($compile, $rootScope, $animate) {
162+
163+
var item;
164+
var $scope = $rootScope.$new();
165+
$scope.on = false;
166+
element = $compile(html(
167+
'<div class="show-hide" ng-show="on">data</div>'
168+
))($scope);
169+
$scope.$digest();
170+
171+
item = $animate.queue.shift();
172+
expect(item.event).toEqual('addClass');
173+
expect(item.options).toEqual('ng-hide-animate');
174+
175+
$scope.on = true;
176+
$scope.$digest();
177+
item = $animate.queue.shift();
178+
expect(item.event).toEqual('removeClass');
179+
expect(item.options).toEqual('ng-hide-animate');
180+
}));
159181
});
160182

161183
describe('ngHide', function() {
@@ -181,5 +203,27 @@ describe('ngShow / ngHide animations', function() {
181203
expect(item.element.text()).toBe('datum');
182204
expect(item.element).toBeShown();
183205
}));
206+
207+
it('should apply the temporary `.ng-hide-animate` class to the element',
208+
inject(function($compile, $rootScope, $animate) {
209+
210+
var item;
211+
var $scope = $rootScope.$new();
212+
$scope.on = false;
213+
element = $compile(html(
214+
'<div class="show-hide" ng-hide="on">data</div>'
215+
))($scope);
216+
$scope.$digest();
217+
218+
item = $animate.queue.shift();
219+
expect(item.event).toEqual('removeClass');
220+
expect(item.options).toEqual('ng-hide-animate');
221+
222+
$scope.on = true;
223+
$scope.$digest();
224+
item = $animate.queue.shift();
225+
expect(item.event).toEqual('addClass');
226+
expect(item.options).toEqual('ng-hide-animate');
227+
}));
184228
});
185229
});

0 commit comments

Comments
 (0)