Les Paul
Les Paul

Reputation: 1278

Using timeout to show and hide custom directive element

I have a directive that inherits scope from its parent controller. The directive is a div element that overlays the page for three seconds then disappears unless an up/down arrow button is clicked. The div element acts as kind of a modal. This is the code on my DOM

HTML

<div ng-show="volumeVisibility">
    <display-volume-modal></display-volume-modal>
</div>

The default setting is false. When volumeVisibility === true, the directive will appear upon a button click. So far, so good. These are my two functions in the controller:

$scope.volumeVisibility = false;

$scope.timer = function(){ 
    console.log("Timer");
    $scope.volumeVisibility = false;
};

$scope.displayVolumeModal = function(){
    $scope.volumeVisibility = true;
    console.log("modal");   
};

The timeout works and sets $scope.volumeVisibility === false. However, the div does not remove itself from the page. Here is the code from the directive (I've removed the irrelevant parts):

return {
    restrict: 'E',
    scope: false,
    link: function(scope, elem, attrs){
        scope.$watch('volumeVisibility', function(newVal, oldVal){
            if (newVal === true){
                window.setTimeout(scope.timer, 3000);           
                document.addEventListener('keydown', function(e){
                    //stuff
                    switch (e.which) {              
                        case 38:
                            //stuff
                            break;
                        case 40:
                            //stuff
                            break;
                    }
                });
            }
        }, true);
    },
    templateUrl: 'public/templates/displayVolumeModal.html'
}

I've tried putting each function into the directive or the controller. What step can I take to make this directive DIV element disappear after timeout?

Upvotes: 0

Views: 1504

Answers (3)

Rohit
Rohit

Reputation: 221

If you use ng-show and ng-hide it will simply make the visibility hidden of the particular html element on which it is applied. The element will be there in the DOM, no matter if it's ng-hide or ng-show. This is why the directive is not being called.

If you want to call the directive everytime it appears on the screen, simply use ng-if instead of ng-show.

Upvotes: 0

Sharikov Vladislav
Sharikov Vladislav

Reputation: 7269

Nothing happens because no digest cycle was called.

To update sync, you have to run digest cycle. I think, in this case, you can use $timeout service instead of setTimeout.

Benefits of $timeout service:

  • unit testable
  • $digest cycle starts after function you passed to the timeout

Upvotes: 1

Ruslan Stelmachenko
Ruslan Stelmachenko

Reputation: 5420

window.setTimeout(scope.timer, 3000); does not call angular digest cycle, so watch doesn't see the changes.

Use angular's $timeout service instead like this:

$timeout(scope.timer, 3000);

Internally it does the same as window.setTimeout, but makes sure, that digest will be called after.

Read more about angular digest cycle and how angular checks if some variable changed. Especially the Integration with the browser event loop chapter.

Upvotes: 1

Related Questions