在Angular JS中的控制器之间传递数据?

kis*_*nio 239 javascript angularjs angular-services

我有一个显示我的产品的基本控制器,

App.controller('ProductCtrl',function($scope,$productFactory){
     $productFactory.get().success(function(data){
           $scope.products = data;
     });
});
Run Code Online (Sandbox Code Playgroud)

在我看来,我在列表中显示这些产品

<ul>
    <li ng-repeat="product as products">
        {{product.name}}
    </li>
</ul
Run Code Online (Sandbox Code Playgroud)

我想要做的是当有人点击产品名称时,我有另一个名为cart的视图,其中添加了此产品.

 <ul class="cart">
      <li>
          //click one added here
      </li>
      <li>
          //click two added here
      </li>
 </ul>
Run Code Online (Sandbox Code Playgroud)

所以我的疑问是,如何将这个点击的产品从第一个控制器传递到第二个?我认为购物车也应该是一个控制器.

我使用指令处理click事件.另外我觉得我应该使用服务来实现上述功能只是无法想象如何?因为购物车将是预定义的,所添加的产品数量可能是5/10,具体取决于用户所在的页面.所以我想保持这种通用性.

更新:

我创建了一个广播服务,在第二个控制器中我收到它.现在查询是如何更新dom的?由于我的产品列表是非常硬编码的.

Cha*_*ise 319

从描述中,似乎您应该使用服务.查看http://egghead.io/lessons/angularjs-sharing-data-between-controllersAngularJS Service在控制器之间传递数据以查看一些示例.

您可以定义您的产品服务(作为工厂):

app.factory('productService', function() {
  var productList = [];

  var addProduct = function(newObj) {
      productList.push(newObj);
  };

  var getProducts = function(){
      return productList;
  };

  return {
    addProduct: addProduct,
    getProducts: getProducts
  };

});
Run Code Online (Sandbox Code Playgroud)

依赖关系将服务注入两个控制器.

在您的ProductController定义中,定义一些将所选对象添加到数组的操作:

app.controller('ProductController', function($scope, productService) {
    $scope.callToAddToProductList = function(currObj){
        productService.addProduct(currObj);
    };
});
Run Code Online (Sandbox Code Playgroud)

在您CartController的服务中,获取产品:

app.controller('CartController', function($scope, productService) {
    $scope.products = productService.getProducts();
});
Run Code Online (Sandbox Code Playgroud)

  • 当调用getProducts()时,Cart控制器将更新一次?或者每次添加新产品? (3认同)
  • @krillgar你完全正确,最初被忽略了.我编辑了答案,以反映一个有效的解决方案. (2认同)

Max*_*tin 67

如何将这个点击的产品从第一个控制器传递到第二个?

单击时,您可以调用调用广播的方法:

$rootScope.$broadcast('SOME_TAG', 'your value');
Run Code Online (Sandbox Code Playgroud)

第二个控制器会监听这个标签,如:

$scope.$on('SOME_TAG', function(response) {
      // ....
})
Run Code Online (Sandbox Code Playgroud)

由于我们无法将$ scope注入服务,因此没有像单例$范围那样的东西.

但我们可以注射$rootScope.因此,如果将值存储到服务中,则可以$rootScope.$broadcast('SOME_TAG', 'your value');在服务主体中运行.(参见@Charx关于服务的描述)

app.service('productService',  function($rootScope) {/*....*/}
Run Code Online (Sandbox Code Playgroud)

请查看关于 $ broadcast,$ emit的好文章

  • @KT - 你有没有得到答案?这似乎是一个显而易见的问题,但我在任何地方都找不到答案。我想要一个控制器来改变一些值。当该应用程序值更改时,任何其他监听控制器都应根据需要自行更新。找不到。 (2认同)
  • @daylight你q的答案.基于您拥有的控制器结构:parallel或child-parent.`$ rootScope.$ broadcast`通知所有具有并行结构的控制器,即同一级别. (2认同)

San*_*eev 24

使用$ rootScope创建Service的解决方案:

要在应用控制器之间共享属性,您可以使用Angular $ rootScope.这是另一种共享数据的选项,可以让人们了解它.

跨控制器共享某些功能的首选方法是服务,以读取或更改可以使用$ rootscope的全局属性.

var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = true;
}]);

app.controller('Ctrl2', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = false;
}]);
Run Code Online (Sandbox Code Playgroud)

在模板中使用$ rootScope(使用$ root访问属性):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 应尽可能避免使用`$ rootScope`. (26认同)
  • @Mirko你应该尽可能地避免全局状态,因为任何人都可以改变它 - 使你的程序状态变得不可预测. (5认同)
  • $ rootScope具有全局范围,因此与本机全局变量一样,我们必须小心使用它们.如果任何控制器更改其值,则它将针对全局范围进行更改. (4认同)
  • 服务是单身,也有全球范围....所以,呃......同样的问题. (3认同)

Nis*_*sin 16

您可以通过两种方法完成此操作.

  1. 通过使用$rootscope,但我不推荐这个.这$rootScope是最顶级的范围.一个应用程序只能有一个$rootScope将在应用程序的所有组件之间共享.因此它就像一个全局变量.

  2. 使用服务.您可以通过在两个控制器之间共享服务来完成此操作.服务代码可能如下所示:

    app.service('shareDataService', function() {
        var myList = [];
    
        var addList = function(newObj) {
            myList.push(newObj);
        }
    
        var getList = function(){
            return myList;
        }
    
        return {
            addList: addList,
            getList: getList
        };
    });
    
    Run Code Online (Sandbox Code Playgroud)

    你可以在这里看到我的小提琴.

  • @shreedharbhat问题不在于询问是否在页面重新加载中保留数据. (2认同)

Bar*_*ski 9

在控制器之间共享数据的更简单方法是使用嵌套数据结构.而不是,例如

$scope.customer = {};
Run Code Online (Sandbox Code Playgroud)

我们可以用

$scope.data = { customer: {} };
Run Code Online (Sandbox Code Playgroud)

data属性将从父作用域继承,因此我们可以覆盖其字段,保持对其他控制器的访问.


小智 8

angular.module('testAppControllers', [])
    .controller('ctrlOne', function ($scope) {
        $scope.$broadcast('test');
    })
    .controller('ctrlTwo', function ($scope) {
        $scope.$on('test', function() {
        });
    });
Run Code Online (Sandbox Code Playgroud)


小智 7

我在这里看到了答案,它回答了控制器之间共享数据的问题,但是如果我希望一个控制器通知另一个控制器数据已更改的事实(不使用广播),我该怎么办?简单!只需使用著名的访问者模式:

myApp.service('myService', function() {

    var visitors = [];

    var registerVisitor = function (visitor) {
        visitors.push(visitor);
    }

    var notifyAll = function() {
        for (var index = 0; index < visitors.length; ++index)
            visitors[index].visit();
    }

    var myData = ["some", "list", "of", "data"];

    var setData = function (newData) {
        myData = newData;
        notifyAll();
    }

    var getData = function () {
        return myData;
    }

    return {
        registerVisitor: registerVisitor,
        setData: setData,
        getData: getData
    };
}

myApp.controller('firstController', ['$scope', 'myService',
    function firstController($scope, myService) {

        var setData = function (data) {
            myService.setData(data);
        }

    }
]);

myApp.controller('secondController', ['$scope', 'myService',
    function secondController($scope, myService) {

        myService.registerVisitor(this);

        this.visit = function () {
            $scope.data = myService.getData();
        }

        $scope.data = myService.getData();
    }
]);
Run Code Online (Sandbox Code Playgroud)

以这种简单的方式,一个控制器可以更新另一个控制器的某些数据已被更新。

  • 观察者模式(http://en.wikipedia.org/wiki/Observer_pattern)在这里不是更相关吗?访问者模式是另一回事... http://en.wikipedia.org/wiki/Visitor_pattern (3认同)

小智 5

我们可以将数据存储在会话中,并且可以在程序外的任何地方使用它。

$window.sessionStorage.setItem("Mydata",data);
Run Code Online (Sandbox Code Playgroud)

其他地方

$scope.data = $window.sessionStorage.getItem("Mydata");
Run Code Online (Sandbox Code Playgroud)