user2499325
user2499325

Reputation: 429

timeout for ngShow not working as expected

I am struggling on how to make the ngShow to determine the expression in a specified timeout period, it turns out that Angular can evaluate the expression but unable to reflect the changes in the view, here is the code I used

(View)

<button 
    type="button" 
    class="btn btn-primary rule-fade" 
    tooltip="{{ proLang.tooltip.ruleApplyBtnTxt }}" 
    ng-click="applyRule('basic')"
    ng-show="showApplyBtns(selectedRules, selectedObj)"
>

    <span class="glyphicon glyphicon-dashboard"></span>
    Apply Rules
</button>

(Controller) And the controller implementing the showApplyBtn function

//determine whether apply buttons should be shown
$scope.showApplyBtns = function(selectedRules, selectedObj) {
    $timeout(function() {
        return selectedRules.length == 1 && selectedObj.length == 1;
    },500);
};

Angular can determine the result (true or false), but it seems that the view doesn't reflect the changes.

Any help would be appreciated, thanks!

Upvotes: 1

Views: 485

Answers (1)

sfletche
sfletche

Reputation: 49764

Rather than have showApplyBtns return a value, try assigning a value to a scope'ed variable.

Then your button can bind that value to ng-show

<button 
    type="button" 
    class="btn btn-primary rule-fade" 
    tooltip="{{ proLang.tooltip.ruleApplyBtnTxt }}" 
    ng-click="applyRule('basic')"
    ng-show="showApplyBtns"
>

Then change your controller so that applyRule() calls updateShowAppyBtns which will update the bound variable showApplyBtns

$scope.applyRule(...) {
    ...
    $scope.updateShowApplyBtns();
}

//determine whether apply buttons should be shown
$scope.updateShowApplyBtns = function() {
    $timeout(function() {
        $scope.showApplyBtns = $scope.selectedRules.length == 1 && $scope.selectedObj.length == 1;
    },500);
};

Now when updateShowApplyBtns is called the $timeout function will update $scope.showApplyBtns and since that updated value is now bound to the ng-show on your button, your button's visibility will be updated.

EXPLANATION

The problem you were having is your showApplyBtns didn't actually return a value

$scope.showApplyBtns = function(selectedRules, selectedObj){
    $timeout(function(){
        return selectedRules.length == 1 && selectedObj.length == 1;
    },500);
    // return undefined (this is what actually happens here)
};

The anonymous function passed to $timeout returns a value...but this value is swallowed inside the $timeout function and showApplyBtns is left without anything to return, and so it returns the default value of undefined.

As you can imagine, it would not be appropriate for showApplyBtns to wait for $timeout to finish before returning its own value as that would block i/o (it would halt all executions while waiting, which is, by design, hard to do in javascript).

Since showApplyBtns can't wait for $timeout to return a value before returning its own value, there is little left to do other than utilize the persistence of state to manage the update (as illustrated in my answer above).

Hopefully that helps. :)

Upvotes: 2

Related Questions