1

I want to show button(Some Button) while some logic is doing in my app, and then hide this button.

By clicking Some Button I call expand() where set data.loading to true, at this point I want to button appears, when I set data.loading to false I want to button hides, but view is not updates.

<button ng-show="data.loading">Some Button</button>
<button ng-click="expand(data)">Other Button</button>

Function:

$scope.expand = function (data) {
    data.loading = true;
    // Some Button must be visible now
    // Some logic here;
    data.loading = false;
    // Some Button must be invisible now
}

$scope.$apply() - returns error: $apply already in progress

$scope.safeApply() - doesn't throw exception, but doesn't updates view.

$timeout - doesn't updates view.

Sébastien
  • 11,860
  • 11
  • 58
  • 78
Tom A. J.
  • 55
  • 4

3 Answers3

2

Referencing your data model via $scope attribute along with moving your main logic out of current digest cycle (with $timeout or $evalAsync) should fix the “$apply already in progress” message in your case:

$scope.expand = function () {
   $scope.data.loading = true;
   $timeout(function () {
       // Some logic here;
       $scope.data.loading = false;
   });
};

I usually prefer to (1) hold loading progress inside a service, and (2) use promises to manage progress status. In the example below, logicFunction() returns a promise.

$scope.expand = function () {
    progressStatusService.started("Loading something…")
    logicFunction().finally(function () {
        progressStatusService.finished("Loading something…")
    });
};
// progressStatusService implementation left as a challenge to the reader

Global progress service is mostly intended for app-wide loading indication—if loading status only affects one specific widget, then it might be an overhead.

However, the deferred/promises approach could be generally useful and easier to read (see more docs at $q).

Community
  • 1
  • 1
Anton Strogonoff
  • 32,294
  • 8
  • 53
  • 61
1
$scope.expand = function () {
   $scope.data.loading = true;
   // Some Button must be visible now
   // Some logic here;
   $scope.data.loading = false;
   // Some Button must be invisible now
}
Sreehari S
  • 388
  • 1
  • 12
0

Use $scope.data.loading as suggested by @Sreehari and use ng-if in you view instead of ng-show.

Ernesto Schiavo
  • 1,020
  • 2
  • 12
  • 33