AngularJS两个控制器具有共享模型,控制器2没有看到模型的变化

时间:2015-10-14 10:56:11

标签: javascript angularjs models controllers

达到我的角色知识的上限,我一直在围绕这个问题。

基本上我有视频播放器和章节列表指令,每个指令都有一个控制器。控制器使用相同的模型服务,如下所示:

my_attribut:null

在视频播放器控制器中,随着播放器更新的时间,它会找到所需的章节数据并更新model.chapters数据,如下所示:

  .service('VideoPlayerModel', function(){
      var model = this;
      model.chapters = {
          chapterPos: 0,
          targetChapter:null,
          data: []
      },
      model.getVideoData = function() {
          return model.videoData;
      };
      model.setVideoData = function(vData){
        ...
        ...
        ...
      };
  });

在setChapter运行后,我调用 updateChapter: function(currentTime){ var chapters = VideoPlayerModel.chapters; var chaptersCtrl = videoPlayerCtrl.chapters; if (chapters.nextChapter.start <= currentTime) { chapters.chapterPos = chapters.chapterPos + 1; chaptersCtrl.setChapter(); //This finds and sets the Target Chapter } }, ,我可以看到数据模型已更新,结果如下:

console.log(VideoPlayerModel.chapters)

然而,ChapterListCtrl中的手表不会触发,显示ChapterPos的任何屏幕上的项目仍然只显示0的初始值。

控制器如下所示:

Object {chapterPos: 1, targetChapter: Object, data: Array[6], nextChapter: Object}

我尝试了不同的方法并最终得到了这个,不确定我现在是否完全错误的方向。有人可以帮忙吗?

3 个答案:

答案 0 :(得分:0)

您可以使用$broadcast()$on()功能来满足您的要求。

$broadcast()会将事件刷新到其所有子控制器。因此,当您为共享模型设置新值时,可以$broadcast()为所有控制器创建具有新值的事件。

在共享服务中添加广播方法。

model.setVideoData = function(vData){
    UpdateYourModel();
    // Inform that your model is updated 
    $rootScope.$broadcast('modelUpdated');
}

现在,您可以在所有控制器中为事件modelUpdated添加一个侦听器。

$scope.$on('modelUpdated', function () {
     $scope.controllerModel = VideoPlayerModel.getVideoData(); // Update your controller model
}

另外,将$rootScope注入您的服务

.service("VideoPlayerModel", ["$rootScope", function($rootScope){
     // define your service here.
}] );

这就是全部!!!

我希望这会对你有所帮助。

答案 1 :(得分:0)

尝试将观察者更改为:

this.parentNode.prevElementSibling

或者,如果没有达到你想要的效果,你可以通过传递第三个参数来启用深度监视:

$scope.$watch('chapters', function(newValue, oldValue){ 
    $scope.chapters = newValue; 
    console.log("A Change"); // Only runs at initialisation.
});

你的观察者没有开火,因为它始终返回Angular认为未更改的$scope.$watch('chapters', function(newValue, oldValue){ $scope.chapters = newValue; console.log("A Change"); // Only runs at initialisation. }, true); ,因为它通过引用进行检查。您的观察者也可以重构为:

chapters

答案 2 :(得分:0)

您不需要使用$watch$broadcast$on。这可以通过常规JavaScript思考来解决。

您的问题是$scope.chapters = newValue;这是您通过引入与您的服务无关的新对象来破坏控制器使用的绑定的地方。

你应该改为考虑你的服务model.chapters = {..}并说出来!这是我将使用的一个对象。如果我想在任何地方更改此对象中的数据,我将在对象内部切换数据,而不是为我使用的引用分配新对象。

为此,我使用以下方法:

    transferDataList = function (from, to) {
        /*
            http://stackoverflow.com/questions/1232040/empty-an-array-in-javascript
        */
        to.length = 0;
        for (var i = 0; i < from.length; i++) { to.push(from[i]); }
    };

    transferDataMap = function (from, to) {
        /*
            http://stackoverflow.com/questions/684575/how-to-quickly-clear-a-javascript-object
        */
        var member;
        for (member in to) { delete to[member]; }
        for (member in from) { to[member] = from[member]; }
    };

当我想改变对象中的数据时,我不会做:

$scope.chapters = newValue;

相反,我做了:

transferDataMap(newValue, $scope.chapters);

或者:

transferDataList(newValue, $scope.chapters);

这样您就可以保持绑定,并且Angular界面将始终更新。