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;
}
}
});
source to share
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}}
.
source to share
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.
source to share
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)
source to share