¿Pasar datos entre controladores en Angular JS?

Resuelto kishanio asked hace 11 años • 18 respuestas

Tengo un controlador básico que muestra mis productos,

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

En mi opinión, estoy mostrando estos productos en una lista.

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

Lo que intento hacer es que cuando alguien hace clic en el nombre del producto, tengo otra vista llamada carrito donde se agrega este producto.

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

Entonces mi duda aquí es: ¿cómo pasar estos productos en los que se hizo clic del primer controlador al segundo? Supuse que el carrito también debería ser un controlador.

Manejo el evento de clic usando la directiva. También siento que debería usar el servicio para lograr la funcionalidad anterior, pero no puedo entender cómo. Debido a que el carrito estará predefinido, la cantidad de productos agregados podría ser 5/10 dependiendo de qué página sea el usuario. Entonces me gustaría mantener esto genérico.

Actualizar:

Creé un servicio para transmitir y en el segundo controlador lo recibo. Ahora la consulta es ¿cómo actualizo dom? Dado que mi lista para descartar productos está bastante codificada.

kishanio avatar Nov 25 '13 04:11 kishanio
Aceptado

Según la descripción, parece que deberías utilizar un servicio. Consulte http://egghead.io/lessons/angularjs-sharing-data-between-controllers y AngularJS Service Passing Data Between Controllers para ver algunos ejemplos.

Podría definir el servicio de su producto (como una fábrica) como tal:

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

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

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

  return {
    addProduct: addProduct,
    getProducts: getProducts
  };

});

La dependencia inyecta el servicio en ambos controladores.

En su ProductController, defina alguna acción que agregue el objeto seleccionado a la matriz:

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

En tu CartController, consigue los productos del servicio:

app.controller('CartController', function($scope, productService) {
    $scope.products = productService.getProducts();
});
Chalise avatar Nov 24 '2013 21:11 Chalise

¿Cómo pasar estos productos en los que se hizo clic del primer controlador al segundo?

Al hacer clic, puede llamar al método que invoca la transmisión :

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

y el segundo controlador escuchará esta etiqueta como:

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

Como no podemos inyectar $scope en los servicios, no hay nada como un $scope singleton.

Pero podemos inyectar $rootScope. Entonces, si almacena valor en el Servicio, puede ejecutarlo $rootScope.$broadcast('SOME_TAG', 'your value');en el cuerpo del Servicio. (Ver descripción de @Charx sobre servicios)

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

Consulte el buen artículo sobre $broadcast y $emit.

Maxim Shoustin avatar Nov 24 '2013 21:11 Maxim Shoustin

Solución sin crear Servicio, usando $rootScope:

Para compartir propiedades entre controladores de aplicaciones, puede usar Angular $rootScope. Esta es otra opción para compartir datos, poniéndolos de manera que la gente los conozca.

La forma preferida de compartir algunas funciones entre controladores es Servicios; para leer o cambiar una propiedad global puede usar $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;
}]);

Usando $rootScope en una plantilla (Acceda a las propiedades con $root):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>
Sanjeev avatar Aug 27 '2014 19:08 Sanjeev