javascriptangularjsng-showangularjs-ng-show

ng-show not triggered on value=true


I'm trying to display a div when Vimeo video reached the end using ng-show but I can get it to work.

Related part of the controller responsible for ng-show looks like

    'use strict';

    myApp.controller('videoController', [
        '$scope',
        '$routeParams',
        '$rootScope',
        '$location',
        '$log',
        function(
            $scope, 
            $routeParams, 
            $rootScope, 
            $location,
            $log
        )
        {

            var player = new Vimeo.Player('player');
            player.on('timeupdate', function(data) {

            $scope.videoFinished = false;

            $scope.currentPlayDuration = (data.percent * 100).toFixed(1);

            if($scope.currentPlayDuration==100.0){
                $scope.videoFinished = true;
                $log.debug('Video finished: ' + $scope.videoFinished);
                $scope.apply();
            }

        });
    }
]);

and a view for that part:

<div class="row" ng-show="videoFinished">Thank you for watching!</div>

Part where related controller is defined:

myApp.config(['$routeProvider','$locationProvider',function($routeProvider,$locationProvider) {
    $routeProvider
    .when('/video', {
        templateUrl: 'video.html',
        controller: 'videoController'
    })  
    .otherwise({
        redirectTo: '/'
    });

When I run video to the end console will show

Video finished: true

but a div from above is not displayed.

Any clue?


Solution

  • The video player's events happen outside of AngularJS's digest cycle, so you have to manually initiate a digest cycle with $scope.$apply() so that it can pick up the changes:

    player.on('timeupdate', function(data) {
    
        $scope.videoFinished = false;
    
        $scope.currentPlayDuration = (data.percent * 100).toFixed(1);
    
        if ($scope.currentPlayDuration == 100.0) {
            $scope.videoFinished = true;
            $log.debug('Video finished: ' + $scope.videoFinished);
            $scope.$apply();
        }
    });
    

    As a side note, it's not considered good practice to have your controllers interact directly with non-Angular components in the page. The appropriate place to do that would generally be in a custom directive.