我正在尝试跨控制器共享数据。用例是一种多步骤形式,在一个输入中输入的数据稍后将用于原始控制器之外的多个显示位置。下面和jsfiddle中的代码。

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

// 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;
});

任何帮助都非常感激。


当前回答

一个简单的解决方案是让你的工厂返回一个对象,让你的控制器使用同一个对象的引用:

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:

<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>

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

当应用程序变得更大、更复杂、更难测试时,你可能不想以这种方式从工厂中暴露整个对象,而是通过getter和setter来提供有限的访问:

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

    var data = {
        FirstName: ''
    };

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

使用这种方法,由消费控制器来更新工厂的新值,并观察变化以获得它们:

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:

<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>

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

其他回答

一个简单的解决方案是让你的工厂返回一个对象,让你的控制器使用同一个对象的引用:

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:

<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>

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

当应用程序变得更大、更复杂、更难测试时,你可能不想以这种方式从工厂中暴露整个对象,而是通过getter和setter来提供有限的访问:

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

    var data = {
        FirstName: ''
    };

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

使用这种方法,由消费控制器来更新工厂的新值,并观察变化以获得它们:

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:

<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>

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

有许多方法可以在控制器之间共享数据

使用服务 使用美元的状态。去服务 使用stateparams 使用rootscope

各方法说明:

I am not going to explain as its already explained by someone using $state.go $state.go('book.name', {Name: 'XYZ'}); // then get parameter out of URL $state.params.Name; $stateparam works in a similar way to $state.go, you pass it as object from sender controller and collect in receiver controller using stateparam using $rootscope (a) sending data from child to parent controller $scope.Save(Obj,function(data) { $scope.$emit('savedata',data); //pass the data as the second parameter }); $scope.$on('savedata',function(event,data) { //receive the data as second parameter }); (b) sending data from parent to child controller $scope.SaveDB(Obj,function(data){ $scope.$broadcast('savedata',data); }); $scope.SaveDB(Obj,function(data){`enter code here` $rootScope.$broadcast('saveCallback',data); });

我不喜欢使用$watch。您可以只分配数据,而不是将整个服务分配给控制器的作用域。

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:

<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>

或者,您可以使用直接方法更新服务数据。

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);
   }
});

我已经创建了一个工厂来控制路由路径模式之间的共享作用域,因此您可以在用户在相同的路由父路径中导航时维护共享数据。

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

因此,如果用户转到另一个路由路径,例如'/Support',路径'/Customer'的共享数据将被自动销毁。但是,如果用户去到“子”路径,比如“/Customer/1”或“/Customer/list”,作用域不会被销毁。

您可以在这里看到一个示例:http://plnkr.co/edit/OL8of9

有多种方法可以在控制器之间共享数据

角服务 $broadcast, $emit方法 父到子控制器通信 rootscope美元

众所周知,$rootscope不是数据传输或通信的首选方式,因为它是一个全局作用域,可用于整个应用程序

对于Angular Js控制器之间的数据共享,Angular服务是最佳实践,例如.factory, .service 供参考

如果数据从父控制器传输到子控制器,您可以通过$scope直接访问子控制器中的父数据 如果你正在使用ui-router,那么你可以使用$stateParmas来传递url参数,如id,名称,键等

$broadcast也是在控制器之间从父控制器传输数据到子控制器的好方法,$emit是将数据从子控制器传输到父控制器的好方法

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>

JS

myApp.controller('FirstCtrl', function( $rootScope, Data ){
    $rootScope.$broadcast('myData', {'FirstName': 'Peter'})
});

myApp.controller('SecondCtrl', function( $rootScope, Data ){
    $rootScope.$on('myData', function(event, data) {
       $scope.FirstName = data;
       console.log(data); // Check in console how data is coming
    });
});

参考给出的链接了解更多关于$broadcast的信息