Reputation: 15291
I have a directive that toggles a DIV I have using ng-show
. Now when the DIV is visible after 5 seconds I wish it to fade out. The ng-show
is toggled using a $scope
variable in my controller ($scope.showPopover
) which is a boolean, it is either true or false. This is my HTML:
Hello World, I am content but will go after 5 seconds!
You will notice the custom directive is on a child div as in my directive when I tried to use the element it was returning the comment produced by the ng-if
. This is my directive
.directive('fadeAnimation', function ($animate) {
'use strict';
return{
restrict: 'A',
priority: 800,
link: function (scope, element) {
scope.$watch('showPopover', function (newValue) {
console.log(scope.showPopover); // same as scope.showPopover in the controller
if (newValue === true) {
$animate.addClass(element[0].parentNode, 'fade-animiate').then(function () {
$animate.removeClass(element[0].parentNode, 'fade-animiate');
//scope.showPopover = false;
// scope.$apply(); // this produces Error: [$rootScope:inprog] $digest already in progress
});
} else if (newValue === false) {
//scope.showPopover = false;
// scope.$apply(); // this produces Error: [$rootScope:inprog] $digest already in progress
}
});
}
};
});
As you can see I add and remove a CSS class (with animation) to the parent element. Once this is done I would like to set the scope.showPopover boolean that is in the controller to false as this prevents me having to double click the original link that toggles the popover (as it is false, we toggle to true, the animation hides the DIV but the scope.showPopover
or $scope.showPopover
is still true). I have tried setting scope.showPopover = false
in my directive but this is not updated in the controller. When I try and force a scope.$apply(); I get an error in my console stating Error: [$rootScope:inprog] $digest already in progress
. What am I doing wrong?
I have tried setting this in the promise after I remove the css class and when I uncomment the scope.showPopover = false
(in the newValue === true
condition) the watch doesn't see this change and the watch breaks the next time I toggle the $scope.showPopover
in the view. Nothing seems to work, I assume my approach is wrong! Any ideas? Many thanks in advance!
Upvotes: 0
Views: 152
Reputation: 1930
You should try using 2-way binding in your directive
HTML
<div ng-show="showPopover" class="popover" fade-animation show-popover="showPopover">Hello World, I am content but will go after 5 seconds!</div>
DIRECTIVE
app.directive('fadeAnimation', function() {
return {
restrict: 'A',
scope: {
showPopover: "="
},
link: function(scope, element, attr) {
element.addClass('fade-animation');
scope.$watch("showPopover", function(value) {
if(value){
//you should be able to flip the boolean here and see it in the controller
}
});
}
};
});
Upvotes: 0
Reputation: 2113
Not sure it fit with your requirement, i used animation hooks to trigger the fade:
Javascript
app.directive('fadeAnimation', function ($timeout) {
return {
restrict: 'A',
link: function(scope, element, attr) {
element.addClass('fade-animation');
scope.$watch(attr.ngShow, function (value) {
if(value){
$timeout(function(){ scope.showPopover = false; },5000);
}
});
}
};
})
CSS:
.fade-animation.ng-hide-add.ng-hide-add-active,
.fade-animation.ng-hide-remove.ng-hide-remove-active {
-webkit-transition: all linear 1s;
transition: all linear 1s;
}
.fade-animation {
opacity: 1;
}
.fade-animation.ng-hide {
opacity: 0;
}
Upvotes: 0