在AngularJS控制器之间共享数据

本文翻译自:Share data between AngularJS controllers

I'm trying to share data across controllers. 我正在尝试跨控制器共享数据。 Use-case is a multi-step form, data entered in one input is later used in multiple display locations outside the original controller. 用例是一种多步形式,在一个输入中输入的数据稍后用于原始控制器外的多个显示位置。 Code below and in jsfiddle here . 下面的代码和jsfiddle这里

HTML HTML

<div ng-controller="FirstCtrl">
    <input type="text" ng-model="FirstName"><!-- Input entered here -->
    <br>Input is : <strong>{{FirstName}}</strong><!-- Successfully updates here -->
</div>

<hr>

<div ng-controller="SecondCtrl">
    Input should also be here: {{FirstName}}<!-- How do I automatically updated it here? -->
</div>

JS JS

// declare the app with no dependencies
var myApp = angular.module('myApp', []);

// make a factory to share data between controllers
myApp.factory('Data', function(){
    // I know this doesn't work, but what will?
    var FirstName = '';
    return FirstName;
});

// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){

});

// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
    $scope.FirstName = Data.FirstName;
});

Any help is greatly appreciated. 任何帮助是极大的赞赏。


#1楼

参考:https://stackoom.com/question/1TyNm/在AngularJS控制器之间共享数据


#2楼

A simple solution is to have your factory return an object and let your controllers work with a reference to the same object: 一个简单的解决方案是让您的工厂返回一个对象,让您的控制器使用对同一对象的引用:

JS: JS:

// declare the app with no dependencies
var myApp = angular.module('myApp', []);

// Create the factory that share the Fact
myApp.factory('Fact', function(){
  return { Field: '' };
});

// Two controllers sharing an object that has a string in it
myApp.controller('FirstCtrl', function( $scope, Fact ){
  $scope.Alpha = Fact;
});

myApp.controller('SecondCtrl', function( $scope, Fact ){
  $scope.Beta = Fact;
});

HTML: HTML:

<div ng-controller="FirstCtrl">
    <input type="text" ng-model="Alpha.Field">
    First {{Alpha.Field}}
</div>

<div ng-controller="SecondCtrl">
<input type="text" ng-model="Beta.Field">
    Second {{Beta.Field}}
</div>

Demo: http://jsfiddle.net/HEdJF/ 演示: http //jsfiddle.net/HEdJF/

When applications get larger, more complex and harder to test you might not want to expose the entire object from the factory this way, but instead give limited access for example via getters and setters: 当应用程序变得更大,更复杂且更难测试时,您可能不希望以这种方式从工厂公开整个对象,而是通过getter和setter提供有限的访问权限:

myApp.factory('Data', function () {

    var data = {
        FirstName: ''
    };

    return {
        getFirstName: function () {
            return data.FirstName;
        },
        setFirstName: function (firstName) {
            data.FirstName = firstName;
        }
    };
});

With this approach it is up to the consuming controllers to update the factory with new values, and to watch for changes to get them: 通过这种方法,消费控制器可以使用新值更新工厂,并观察更改以获取它们:

myApp.controller('FirstCtrl', function ($scope, Data) {

    $scope.firstName = '';

    $scope.$watch('firstName', function (newValue, oldValue) {
        if (newValue !== oldValue) Data.setFirstName(newValue);
    });
});

myApp.controller('SecondCtrl', function ($scope, Data) {

    $scope.$watch(function () { return Data.getFirstName(); }, function (newValue, oldValue) {
        if (newValue !== oldValue) $scope.firstName = newValue;
    });
});

HTML: HTML:

<div ng-controller="FirstCtrl">
  <input type="text" ng-model="firstName">
  <br>Input is : <strong>{{firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
  Input should also be here: {{firstName}}
</div>

Demo: http://jsfiddle.net/27mk1n1o/ 演示: http //jsfiddle.net/27mk1n1o/


#3楼

I prefer not to use $watch for this. 我不想使用$watch这件事。 Instead of assigning the entire service to a controller's scope you can assign just the data. 您可以只分配数据,而不是将整个服务分配给控制器的范围。

JS: JS:

var myApp = angular.module('myApp', []);

myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    }
    // Other methods or objects can go here
  };
});

myApp.controller('FirstCtrl', function($scope, MyService){
  $scope.data = MyService.data;
});

myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;
});

HTML: HTML:

<div ng-controller="FirstCtrl">
  <input type="text" ng-model="data.firstName">
  <br>Input is : <strong>{{data.firstName}}</strong>
</div>
<hr>
<div ng-controller="SecondCtrl">
  Input should also be here: {{data.firstName}}
</div>

Alternatively you can update the service data with a direct method. 或者,您可以使用直接方法更新服务数据。

JS: JS:

// A new factory with an update method
myApp.factory('MyService', function(){
  return {
    data: {
      firstName: '',
      lastName: ''
    },
    update: function(first, last) {
      // Improve this method as needed
      this.data.firstName = first;
      this.data.lastName = last;
    }
  };
});

// Your controller can use the service's update method
myApp.controller('SecondCtrl', function($scope, MyService){
   $scope.data = MyService.data;

   $scope.updateData = function(first, last) {
     MyService.update(first, last);
   }
});

#4楼

I've created a factory that controls shared scope between route path's pattern, so you can maintain the shared data just when users are navigating in the same route parent path. 我创建了一个控制路径路径模式之间共享范围的工厂,因此您可以在用户在同一路径父路径中导航时维护共享数据。

.controller('CadastroController', ['$scope', 'RouteSharedScope',
    function($scope, routeSharedScope) {
      var customerScope = routeSharedScope.scopeFor('/Customer');
      //var indexScope = routeSharedScope.scopeFor('/');
    }
 ])

So, if the user goes to another route path, for example '/Support', the shared data for path '/Customer' will be automatically destroyed. 因此,如果用户转到另一个路径路径,例如'/ Support',路径'/ Customer'的共享数据将自动销毁。 But, if instead of this the user goes to 'child' paths, like '/Customer/1' or '/Customer/list' the the scope won't be destroyed. 但是,如果不是这样,用户转到'子'路径,如'/ Customer / 1'或'/ Customer / list',则不会破坏范围。

You can see an sample here: http://plnkr.co/edit/OL8of9 您可以在此处查看示例: http//plnkr.co/edit/OL8of9


#5楼

Just do it simple (tested with v1.3.15): 只是做到这一点(用v1.3.15测试):

<article ng-controller="ctrl1 as c1">
    <label>Change name here:</label>
    <input ng-model="c1.sData.name" />
    <h1>Control 1: {{c1.sData.name}}, {{c1.sData.age}}</h1>
</article>
<article ng-controller="ctrl2 as c2">
    <label>Change age here:</label>
    <input ng-model="c2.sData.age" />
    <h1>Control 2: {{c2.sData.name}}, {{c2.sData.age}}</h1>
</article>

<script>
    var app = angular.module("MyApp", []);

    var dummy = {name: "Joe", age: 25};

    app.controller("ctrl1", function () {
        this.sData = dummy;
    });

    app.controller("ctrl2", function () {
        this.sData = dummy;
    });
</script>


#6楼

Not sure where I picked up this pattern but for sharing data across controllers and reducing the $rootScope and $scope this works great. 不知道我在哪里选择这种模式,但是为了跨控制器共享数据并减少$ rootScope和$ scope,这非常有用。 It is reminiscent of a data replication where you have publishers and subscribers. 它让人联想到您拥有发布者和订阅者的数据复制。 Hope it helps. 希望能帮助到你。

The Service: 服务:

(function(app) {
    "use strict";
    app.factory("sharedDataEventHub", sharedDataEventHub);

    sharedDataEventHub.$inject = ["$rootScope"];

    function sharedDataEventHub($rootScope) {
        var DATA_CHANGE = "DATA_CHANGE_EVENT";
        var service = {
            changeData: changeData,
            onChangeData: onChangeData
        };
        return service;

        function changeData(obj) {
            $rootScope.$broadcast(DATA_CHANGE, obj);
        }

        function onChangeData($scope, handler) {
            $scope.$on(DATA_CHANGE, function(event, obj) {
                handler(obj);
            });
        }
    }
}(app));

The Controller that is getting the new data, which is the Publisher would do something like this.. 获取新数据的Controller,即发布者将执行此类操作。

var someData = yourDataService.getSomeData();

sharedDataEventHub.changeData(someData);

The Controller that is also using this new data, which is called the Subscriber would do something like this... 同样使用这个新数据的Controller,称为订阅者,会做这样的事......

sharedDataEventHub.onChangeData($scope, function(data) {
    vm.localData.Property1 = data.Property1;
    vm.localData.Property2 = data.Property2;
});

This will work for any scenario. 这适用于任何场景。 So when the primary controller is initialized and it gets data it would call the changeData method which would then broadcast that out to all the subscribers of that data. 因此,当初始化主控制器并获取数据时,它将调用changeData方法,然后将该方法广播给该数据的所有订户。 This reduces the coupling of our controllers to each other. 这减少了我们的控制器之间的耦合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值