Angularjs:在控制器之间共享可观察数据

时间:2014-09-01 14:57:59

标签: angularjs observable

我需要在几个控制器中使用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是否有最佳实践或更好的方法?

3 个答案:

答案 0 :(得分:2)

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

在您的示例中,您有两个控制器在$ scope上具有相同的数据,也许您应该引用一个管理$ 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执行不同的操作时,事情变得更有趣。在这种情况下,您可能需要根据需要在控制器之间进行一些同步。关于控制器之间共享状态和控制器之间通信的问题有很多答案。

答案 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可以监听并执行您的逻辑(反之亦然)。

以下是解释:http://mariuszprzydatek.com/2013/12/28/sharing-data-between-controllers-in-angularjs-pubsub-event-bus-example/

OR 一种肮脏的方式可能是使用 $ rootScope 来处理所有应用程序中的相同数据,因此当它发生变化时,它会改变工作流程中的任何位置。

希望有所帮助