AngularJS - share variable between two controllers

I have two controllers that have to communicate with each other. The first link is to the video player, and the second to the timeline.

From the first I am getting currentTime

a video playback and I want to pass it to the second one, which should move the time bar as the video plays.

I've tried using a factory to exchange a named variable time

between controllers, but this doesn't change over time.

First controller :

angular.module('videoCtrl', ['vjs.video'])
  .controller('videoController', ['$scope', 'Timeline', function (scope, Timeline) {
        scope.mediaToggle = {
            sources: [
                {
                    src: 'http://static.videogular.com/assets/videos/videogular.mp4',
                    type: 'video/mp4'
                }
            ],
        };

        //listen for when the vjs-media object changes
        scope.$on('vjsVideoReady', function (e, videoData) {
          videoData.player.on('timeupdate', function () {
            var time = this.currentTime();
            Timeline.setTime(time); // setting the time on factory
          })
        });
    }]);

      

Second controller :

angular.module('timelineCtrl', ['mt.media-timeline'])
    .controller('timelineController', function ($scope, Timeline) {
    $scope.time = Timeline.getTime(); // here I'm trying to get the time
  });

      

Factory

.factory('Timeline', function(){
    var timelines = [];
    var time = null;
    return {

      getTime: function() {
        return time;
      },

      setTime: function(_time) {
        time = _time;
      }

    }
  });

      

+3


source to share


3 answers


time

appears to be primitive, which means it returns byVal and not byRef . In other words, each call will getTime

return the value that is currently set to time

, and the calls setTime

will change the value for future calls, but not for what has already called it. This is a classic example of angular rule, always use period.

Try changing time

to object instead :



.factory('Timeline', function() {
  var timelines = [];
  var time = {
    value: null
  };
  return {

    getTime: function() {
      return time;
    },

    setTime: function(_time) {
      time.value = _time;
    }

  }
});

      

In your HTML, use {{time.value}}

.

+5


source


Saving in $rootScope

instead $scope

will give you the ability to access the variable across all applications and your controllers. But keep in mind that creating a lot of $ rootScope can affect the performance of your application.



Don't forget to inject $rootScope

into the controller (using $ scope for example) so you can access it.

0


source


Okay, as far as I can tell, what is doing in the second controller is that you return the time value when you instantiate the controller. Of course, further changes in the cost of the service cannot be matched in this way. To do this, in the second controller, you can use $scope.$watch

:

angular.module('timelineCtrl', ['mt.media-timeline'])
    .controller('timelineController', function ($scope, Timeline) {
    $scope.time = Timeline.getTime(); //Set the time once so it not undefined

    $scope.$watch(
      function() {return Timeline.getTime();},
      function(newVal) {$scope.time = newVal;}
    );
});

      

Angular will call the first function every loop $digest

(about at least every 10ms if I remember correctly) and will call the second function when a change is detected. Detailed documentation for $watch

can be found here

This is one way to do it. You can also add a function to $scope

(eg getTime()

), which should return the current time, and then call this function in the HTML template: {{getTime()}}

. Both ways pretty much work the same, except that the second leaves the dirty work up to angular (creating observers and updating values)

0


source







All Articles