3

Within a factory service, I have to use

$http.get(url, { cache: true })

In my view, i am using ng-if or ng-show to trigger a CSS transition.


The problem :

It is working great for the first request, but obviously for the next request of the same service function, the animation is not re-triggered.

Is there a way to reset / retrigger the ng-if / ng-show animation ?

(The cache is needed so i can avoid waiting time, but i still need to have opacity animation triggered between different states).

Thank you !


app.factory('progService', function ($http) {
    var progService= {};
    progService.getProgram = function() {
        return $http.get(appInfo.api_url + 'pages/5', { cache: true});
    };
    return progService;
});


app.controller('programController', function($scope, progService) {
    progService.getProgram().then(function(res){
        $scope.program = res.data;
    });
});


<div ng-if="program.aJsonKey"></div>
jDelforge
  • 129
  • 4
  • 15

2 Answers2

2

Your view is not updated because you're passing the same, cached object. In order to execute the $watcher of ngIf, you should provide a "fresh"/new object. You would also need probably to change the state, because ngIf would expect true or false. So in your case should be something like this:

app.controller('programController', function($scope, progService) {
    $scope.program = null;
    progService.getProgram().then(function(res){
        $scope.program = angular.copy(res.data); // Returns a copy of the object. Always a new object!
    });
});
Yavor Ivanov
  • 119
  • 3
  • Thanx Yavor. But the animation only retriggers if i put a short *setTimout* around `$scope.program = angular.copy(res.data);` **or** `angular.element(document).ready(function () { ` + `});` around it. **But then** for both tricks the first request seems way longer. – jDelforge Apr 11 '16 at 21:16
  • 1
    You should avoid using setTimeout in Angular. There's abstraction over it and is called $timeout service, you should use it instead of pure setTimeout: https://docs.angularjs.org/api/ng/service/$timeout And, yes, if your service is mocked/ does not make an AJAX call probably you won't get an animation, because you have a sync code. Using timeout to show animation should be fine to trigger the animation – Yavor Ivanov Apr 12 '16 at 07:36
  • 1
    Also from your writing I see that it's DOM might not be ready yet. So workarounds are to use .ready() or $timeout/setTimeout. – Yavor Ivanov Apr 12 '16 at 07:42
  • Indeed... i had other problems because of using additional sliders on the page. So neither .ready() or setTimeout would work well (sometimes waiting for the other slider to achieve slide transition)... Right now I am using $timeout which is way better, but not perfect (sometimes it still happen too early). But i don't know much about $timeout, i guess i'll take better use of it in the future. – jDelforge Apr 13 '16 at 03:37
1

you probably need to set up your own flag in this case. for example:

app.controller('programController', function($scope, progService) {

    $scope.programDisplay = false;

    progService.getProgram().then(function(res){
        $scope.program = res.data;
        angular.element(document).ready(function () { 
            $scope.programDisplay = true;
        });
    });
});

then

<div ng-if="program.acf.exerpt && programDisplay"></div>
jDelforge
  • 129
  • 4
  • 15
Zhiliang Xing
  • 1,057
  • 1
  • 8
  • 19
  • Well finally it does work, but **only if** i put a setTimeout around `$scope.programDisplay = true;`, even at 1 millisec. !! Thank you ! – jDelforge Apr 11 '16 at 20:20
  • 1
    how does it look like when it's not working if you dont use setTimeout? can you describe it? – Zhiliang Xing Apr 11 '16 at 20:26
  • If i don't use setTimeout, it seems the flag is always true (from 2nd request), never false, so the animation is not re-triggered. Putting a millisec gap makes the difference... The same trick is needed with the other answer from Yavor Ivanov – jDelforge Apr 11 '16 at 20:42
  • 1
    my guess will be, the $scope.programDisplay got resolved before the bowser actually process the whole html document. so how about try `angular.element(document).ready(function () { $scope.programDisplay = true; });` – Zhiliang Xing Apr 11 '16 at 20:44
  • This is the best answer. Thank you. I'll edit your answer. Once approved i will set it as accepted answer. – jDelforge Apr 11 '16 at 21:23