2014-09-01 96 views
4

我需要在多个控制器中使用datacontext。
datacontext可以以不同的方式更改(通过ajax调用,由用户/视图,服务器)。
当datacontext中的数据发生更改时,应通知所有使用datacontext的控制器。Angularjs:在控制器之间共享可观察数据

的DataContext:

var userDataContext = { firstName: "John", lastName: "Doe" }; 

我在每一个例子模拟后端变化与setTimeout的

setTimeout(function() { 
    console.log("change firstname"); 
    userContext.firstName= "Bart"; 
}, 3000); 

这里是淘汰赛,它工作正常的小提琴例子。
http://jsfiddle.net/8ct0L1zu/4/


我也试图与做到这一点,但它部分地工作。

  • 当我将完整的对象传递给控制器​​(通过引用)时,更改在控制器之间起作用。
    在javascript/backend中更改datacontext时,它不会更改我的视图。

  • 我也更喜欢在控制器范围内只有名字和姓氏,而不是完整的对象。
    但在这种情况下,没有任何工作。
    原因:在我们的应用程序中,会有大量的数据上下文与数组大对象。

http://jsfiddle.net/19xv3skn/1/


要真正让它工作,我以前角与淘汰赛。数据绑定和数据上下文挖掘的角度。这工作正常,但我不太喜欢这个解决方案。
http://jsfiddle.net/7chp5xLa/2/


有一个最佳实践或更好的方式与角度观察到的一个的DataContext工作?

回答

2

我认为这个问题可能是您考虑在AngularJS应用程序中管理数据的方式。您正在编辑AngularJS生命周期之外的userContext数据。不要管理AngularJS“看到”什么,而是在将数据提供给AngularJS后编辑数据。相反,请考虑在Angular内部更改userContext状态,在那里您需要它

在您的示例中,您有两个控制器在$ scope上具有相同的数据,也许您应该参考管理数据的公共父控制器为$范围,而不是:

jsfiddle

app.controller('ParentCtrl', function ($scope, userContext, $timeout) { 
    $scope.firstName = userContext.firstName; 
    $scope.lastName = userContext.lastName; 
    $scope.user = userContext; 
    $timeout(function() { 
     console.log("change firstname"); 
     userContext.firstName= "Bart"; 
    }, 3000); 
}); 

,事情就当你想要做不同的事情,并与每个控制器的UserContext更有趣。在这种情况下,您可能需要根据您的需要在控制器之间进行一些同步。关于在控制器之间共享状态和在控制器之间进行通信的问题有很多答案。

+0

这个想法是“在datacontext和view之间没有链接”。 当我使用ParentCtrl时,我的数据被链接到特定的视图。 我的数据不需要关于ui的任何知识,它的刚好可以被任何控制器/视图使用的数据。 – 2014-09-02 08:10:35

+0

这是真的userContext是在他的生命周期之外。 Angular使用称为脏检查的技术观察变量。 所以你只能使用控制器内部的变量。 Knockout使用Observable模式。这对我来说效果更好。 http://blog.nebithi.com/knockoutjs-vs-angularjs/ 对我来说不会有完美的解决方案:s – 2014-09-02 08:46:16

+0

的确,它完全取决于您的需求,无论Knockout还是AngularJs都是最合适的。 – 2014-09-02 09:14:37

0

也许我没有得到你所需要的正确,但是我建议你得到一看$broadcast

可以播放控制器之间的事件,因此,如果在controllerA数据的变化,然后controllerB可以听和执行逻辑(反之亦然)当事件被解雇时。

这里有一个解释:http://mariuszprzydatek.com/2013/12/28/sharing-data-between-controllers-in-angularjs-pubsub-event-bus-example/

一个肮脏的方式可以是使用$ rootScope来处理所有的应用程序相同的数据,所以当它改变它的工作流程无处不在改变。

希望它有帮助

2

你有几个选项。

1-使用服务和广播事件。

// service 
app.service("DataService", function($rootScope) { 
    var _name = ''; 
    var result = { 
     setName : function(name) { 
      _name = name; 
      $rootScope.$broadcast("nameChanged", _name); 
     }, 
     getName : function() { 
      return _name; 
     } 
    } 
    return result; 
}); 

// controller(s) 
app.controller("ObservingController", function($scope) { 
    $scope.$on("nameChanged", function(name) { 
     console.log("Something changed with name."); 
    }); 
}); 

// other controllers 
app.controller("ModifyingController", function($scope, DataService) { 
    // triggers the broadcast 
    DataService.setName("bob"); 
}); 

2)留意变化与表达

// controller - use the same DataService as above 
app.controller("WatchingController", function($scope, DataService) { 
    // bind the service to the scope for the expression 
    $scope.DataService = DataService; 
    $scope.$watch("DataService.getName()", function(newVal, oldVal) { 
     console.log("Name changed " + newVal); 
    }); 
}); 

这是给你,你喜欢什么。我的服务也写得很差,仅仅是一个例子。 $ rootScope仅用于向所有子范围广播。我不建议在那里存储数据。在数据上下文的情况下,如果将其包装在服务中并公开,则可以将服务(或由服务公开的变量)绑定到示例中,并且您的手表应触发。

// service 
app.service("DataContextService", function() { 
    var context = { 
     firstName : "", 
     lastName : "" 
    }; 
    return { 
     context : context 
    }; 
}); 

// controller 
app.controller("Watcher", function($scope, DataContextService) { 
    $scope.context = DataContextService.context; 
    $scope.$watch("context.firstName", function(newVal, oldVal) { 
     console.log("Change.."); 
    }); 
}); 

app.controller("Modifier", function($scope, DataContextService) { 
    // causes the watch to trigger 
    DataContextService.context.firstName = "Bob"; 
}); 
+0

这和我的解决方案一样安静。 除了我正在使用Knockout并在您的示例中,您正在编程它自己。 Knockout有一个完全可观察的模式,它非常强大(计算好,性能好等),因此我更喜欢使用Knockout来处理DataContextService。 – 2014-09-02 08:35:25

相关问题