247

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

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

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

<ul>
    <li ng-repeat="product as products">
        {{product.name}}
    </li>
</ul

我想要做的是当有人点击产品名称时,我有另一个名为购物车的视图,其中添加了该产品。

 <ul class="cart">
      <li>
          //click one added here
      </li>
      <li>
          //click two added here
      </li>
 </ul>

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

我使用指令处理点击事件。另外我觉得我应该使用服务来实现上述功能只是不知道怎么做?因为购物车将被预定义添加的产品数量可能是 5/10,具体取决于用户所在的页面。所以我想保持这个通用性。

更新:

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

4

18 回答 18

324

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

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

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

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

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

  return {
    addProduct: addProduct,
    getProducts: getProducts
  };

});

依赖项将服务注入到两个控制器中。

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

app.controller('ProductController', function($scope, productService) {
    $scope.callToAddToProductList = function(currObj){
        productService.addProduct(currObj);
    };
});

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

app.controller('CartController', function($scope, productService) {
    $scope.products = productService.getProducts();
});
于 2013-11-24T21:54:58.813 回答
67

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

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

$rootScope.$broadcast('SOME_TAG', 'your value');

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

$scope.$on('SOME_TAG', function(response) {
      // ....
})

由于我们不能将 $scope 注入到服务中,所以没有什么像单例 $scope 一样。

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

app.service('productService',  function($rootScope) {/*....*/}

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

于 2013-11-24T21:42:44.010 回答
25

使用 $rootScope 不创建服务的解决方案:

要跨应用控制器共享属性,您可以使用 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;
}]);

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

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>
于 2014-08-27T19:00:56.460 回答
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
        };
    });
    

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

于 2015-02-12T18:08:47.410 回答
9

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

$scope.customer = {};

我们可以用

$scope.data = { customer: {} };

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

于 2014-10-16T10:29:05.250 回答
8
angular.module('testAppControllers', [])
    .controller('ctrlOne', function ($scope) {
        $scope.$broadcast('test');
    })
    .controller('ctrlTwo', function ($scope) {
        $scope.$on('test', function() {
        });
    });
于 2016-01-26T08:32:33.443 回答
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();
    }
]);

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

于 2015-04-06T08:10:53.637 回答
5

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

$window.sessionStorage.setItem("Mydata",data);

其他地方

$scope.data = $window.sessionStorage.getItem("Mydata");
于 2016-10-04T12:42:32.153 回答
4

1

using $localStorage

app.controller('ProductController', function($scope, $localStorage) {
    $scope.setSelectedProduct = function(selectedObj){
        $localStorage.selectedObj= selectedObj;
    };
});

app.controller('CartController', function($scope,$localStorage) { 
    $scope.selectedProducts = $localStorage.selectedObj;
    $localStorage.$reset();//to remove
});

2

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

$rootScope.$broadcast('SOME_TAG', 'your value');

and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
      // ....
})

3

using $rootScope:

4

window.sessionStorage.setItem("Mydata",data);
$scope.data = $window.sessionStorage.getItem("Mydata");

5

使用角度服务的一种方法:

var app = angular.module("home", []);

app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});

app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});

app.factory('ser1', function(){
return {o: ''};
});
于 2017-11-06T11:28:53.057 回答
3

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

.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

于 2014-09-19T02:05:20.917 回答
3

我不知道它是否会帮助任何人,但基于 Charx(谢谢!)的回答,我创建了简单的缓存服务。随意使用、混音和分享:

angular.service('cache', function() {
    var _cache, _store, _get, _set, _clear;
    _cache = {};

    _store = function(data) {
        angular.merge(_cache, data);
    };

    _set = function(data) {
        _cache = angular.extend({}, data);
    };

    _get = function(key) {
        if(key == null) {
            return _cache;
        } else {
            return _cache[key];
        }
    };

    _clear = function() {
        _cache = {};
    };

    return {
        get: _get,
        set: _set,
        store: _store,
        clear: _clear
    };
});
于 2016-10-03T19:09:12.553 回答
2

使用角度服务的一种方法:

var app = angular.module("home", []);

app.controller('one', function($scope, ser1){
$scope.inputText = ser1;
});


app.controller('two',function($scope, ser1){
$scope.inputTextTwo = ser1;
});

app.factory('ser1', function(){
return {o: ''};
});



<div ng-app='home'>

<div ng-controller='one'>
  Type in text: 
  <input type='text' ng-model="inputText.o"/>
</div>
<br />

<div ng-controller='two'>
  Type in text:
  <input type='text' ng-model="inputTextTwo.o"/>
</div>

</div>

https://jsfiddle.net/1w64222q/

于 2016-12-07T18:51:08.740 回答
2

在您的模块中创建一个工厂并在控制器中添加工厂的引用并在控制器中使用其变量,现在通过在您想要的任何位置添加引用来获取另一个控制器中的数据值

于 2016-06-28T09:03:14.550 回答
1

仅供参考 $scope 对象具有 $emit、$broadcast、$on 和 $rootScope 对象具有相同的 $emit、$broadcast、$on

在此处阅读有关 Angular 发布/订阅设计模式的更多信息

于 2015-11-17T18:04:57.687 回答
1

有三种方法可以做到,

a) 使用服务

b) 利用控制器范围之间的依赖父/子关系。

c) 在 Angular 2.0 中,“As”关键字将数据从一个控制器传递到另一个控制器。

有关示例的更多信息,请查看以下链接:

http://www.tutorial-points.com/2016/03/angular-js.html

于 2016-03-18T07:47:54.090 回答
1

使用 $broadcast 改进@Maxim 提出的解决方案,发送数据不要更改

$rootScope.$broadcast('SOME_TAG', 'my variable');

但要收听数据

$scope.$on('SOME_TAG', function(event, args) {
    console.log("My variable is", args);// args is value of your variable
})
于 2017-01-04T15:04:33.077 回答
0
var custApp = angular.module("custApp", [])
.controller('FirstController', FirstController)
.controller('SecondController',SecondController)
.service('sharedData', SharedData);

FirstController.$inject = ['sharedData'];
function FirstController(sharedData) {
this.data = sharedData.data;
}

SecondController.$inject['sharedData'];
function SecondController(sharedData) {
this.data = sharedData.data;
}

function SharedData() {
this.data = {
    value: 'default Value'
}
}

第一控制器

<div ng-controller="FirstController as vm">
<input type=text ng-model="vm.data.value" />
</div>

第二控制器

 <div ng-controller="SecondController as vm">
    Second Controller<br>
    {{vm.data.value}}
</div>
于 2017-10-01T11:22:16.467 回答
-1

我觉得

最好的办法

是使用$localStorage。(一直工作)

app.controller('ProductController', function($scope, $localStorage) {
    $scope.setSelectedProduct = function(selectedObj){
        $localStorage.selectedObj= selectedObj;
    };
});

您的 cardController 将是

app.controller('CartController', function($scope,$localStorage) { 
    $scope.selectedProducts = $localStorage.selectedObj;
    $localStorage.$reset();//to remove
});

您还可以添加

if($localStorage.selectedObj){
    $scope.selectedProducts = $localStorage.selectedObj;
}else{
    //redirect to select product using $location.url('/select-product')
}
于 2017-07-28T07:19:22.633 回答