我需要在几个控制器中使用datacontext datacontext可以以不同的方式改变(通过ajax调用,通过用户/视图,通过服务器) 当datacontext中的数据发生变化时,应通知所有使用datacontext的控制器。
的datacontext:
var userDataContext = { firstName: "John", lastName: "Doe" };
我在每个例子中模拟了setTimeout的后端更改
setTimeout(function() {
console.log("change firstname");
userContext.firstName= "Bart";
}, 3000);
这是 Knockout 中的一个小提琴示例,它可以正常工作 http://jsfiddle.net/8ct0L1zu/4/
我也尝试用 Angular 来做,但部分工作。
当我将整个对象传递给控制器(通过引用)时,控制器之间的更改将起作用
在javascript / backend中更改datacontext时,它不会改变我的观点。
我也更喜欢在控制器范围内只有名字和姓氏,而不是完整的对象。
但在这种情况下,没有任何作用。
原因:在我们的应用程序中,会有很多带有大对象数组的datacontexts。
http://jsfiddle.net/19xv3skn/1/
为了真正发挥作用,我使用了 Angular with knockout 。用于datacontext的数据绑定和挖掘的角度。这很好,但我真的不喜欢这个解决方案 http://jsfiddle.net/7chp5xLa/2/
在Angular中使用可观察的datacontext是否有最佳实践或更好的方法?
答案 0 :(得分:2)
我认为问题可能是您考虑在AngularJS应用中管理数据的方式。您正在编辑AngularJS生命周期之外的userContext数据。您可以在将数据提供给AngularJS之后编辑数据,而不是管理AngularJS所看到的内容。相反,请考虑在Angular中更改userContext状态,在那里您需要它
在您的示例中,您有两个控制器在$ scope上具有相同的数据,也许您应该引用一个管理$ scope数据的公共父控制器:
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执行不同的操作时,事情变得更有趣。在这种情况下,您可能需要根据需要在控制器之间进行一些同步。关于控制器之间共享状态和控制器之间通信的问题有很多答案。
答案 1 :(得分: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仅用于广播到所有子范围。我不建议在那里存储数据。
对于数据上下文,如果将其包装在服务中并公开它,则可以将服务(或服务公开的变量)绑定到范围,如watch示例中那样,并且应该触发watch。 / p>
// 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";
});
答案 2 :(得分:0)
可能我没有得到你需要的东西,但我建议你去看看$broadcast
您可以在控制器之间广播事件,因此如果控制器A中的数据发生更改,那么当事件被触发时,controllerB可以监听并执行您的逻辑(反之亦然)。
OR 一种肮脏的方式可能是使用 $ rootScope 来处理所有应用程序中的相同数据,因此当它发生变化时,它会改变工作流程中的任何位置。
希望有所帮助