web-dev-qa-db-fra.com

Transmission de données entre contrôleurs dans Angular JS?

J'ai un contrôleur de base qui affiche mes produits,

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

À mon avis, j'affiche ces produits dans une liste

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

Ce que j'essaie de faire, c'est quand quelqu'un clique sur le nom du produit, j'ai une autre vue nommée cart où ce produit est ajouté.

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

Donc, mon doute est de savoir comment passer ces produits sélectionnés du premier contrôleur au second? J'ai supposé que le chariot devrait aussi être un contrôleur.

Je gère l'événement click à l'aide d'une directive. En outre, j'estime que je devrais utiliser le service pour obtenir les fonctionnalités ci-dessus, mais je ne vois pas comment? parce que le panier sera prédéfini nombre de produits ajoutés pourrait être 5/10 en fonction de la page de l'utilisateur. Je voudrais donc garder ce générique.

Mettre à jour:

J'ai créé un service de diffusion et je le reçois dans le second contrôleur. Maintenant, la requête est comment puis-je mettre à jour dom? Depuis ma liste de produits à déposer est assez codé.

235
kishanio

De la description, semble que vous devriez utiliser un service. Consultez http://egghead.io/lessons/angularjs-sharing-data-between-controllers et service AngularJS transmettant des données entre contrôleurs pour voir des exemples.

Vous pouvez définir votre service produit (en tant qu’usine) comme suit:

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

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

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

  return {
    addProduct: addProduct,
    getProducts: getProducts
  };

});

La dépendance injecte le service dans les deux contrôleurs.

Dans votre ProductController, définissez une action qui ajoute l'objet sélectionné au tableau:

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

Dans votre CartController, obtenez les produits du service:

app.controller('CartController', function($scope, productService) {
    $scope.products = productService.getProducts();
});
318
Chalise

comment passer les produits sur lesquels vous avez cliqué du premier contrôleur au second?

Au clic, vous pouvez appeler une méthode qui appelle broadcast :

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

et le second contrôleur va écouter sur cette balise comme:

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

Comme nous ne pouvons pas injecter $ scope dans les services, il n’ya rien de mieux que singleton $ scope.

Mais nous pouvons injecter $rootScope. Ainsi, si vous stockez une valeur dans le service, vous pouvez exécuter $rootScope.$broadcast('SOME_TAG', 'your value'); dans le corps du service. (Voir la description de @Charx sur les services)

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

Vérifiez le bon article sur $ broadcast , $ emit

66
Maxim Shoustin

Solution sans créer de service, en utilisant $ rootScope:

Pour partager des propriétés entre plusieurs contrôleurs d'applications, vous pouvez utiliser Angular $ rootScope. C'est une autre option pour partager des données, en les mettant de manière à ce que les gens le sachent.

Le moyen privilégié de partager certaines fonctionnalités entre les contrôleurs est les services. Pour lire ou modifier une propriété globale, vous pouvez utiliser $ 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;
}]);

Utilisation de $ rootScope dans un modèle (propriétés d’accès avec $ root):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>
24
Sanjeev

Vous pouvez le faire de deux manières.

  1. En utilisant $rootscope, mais je ne recommande pas cela. Le $rootScope est la plus grande portée. Une application ne peut avoir qu'un seul $rootScope qui sera partagé entre tous les composants d'une application. Par conséquent, il agit comme une variable globale.

  2. Utilisation des services. Vous pouvez le faire en partageant un service entre deux contrôleurs. Le code de service peut ressembler à ceci:

    app.service('shareDataService', function() {
        var myList = [];
    
        var addList = function(newObj) {
            myList.Push(newObj);
        }
    
        var getList = function(){
            return myList;
        }
    
        return {
            addList: addList,
            getList: getList
        };
    });
    

    Vous pouvez voir mon violon ici .

16
Nisham Mahsin

Une méthode encore plus simple de partage des données entre contrôleurs consiste à utiliser des structures de données imbriquées. Au lieu de, par exemple

$scope.customer = {};

on peut utiliser

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

La propriété data sera héritée de la portée parent afin que nous puissions écraser ses champs, en conservant l'accès depuis d'autres contrôleurs.

9
Barth Zalewski
angular.module('testAppControllers', [])
    .controller('ctrlOne', function ($scope) {
        $scope.$broadcast('test');
    })
    .controller('ctrlTwo', function ($scope) {
        $scope.$on('test', function() {
        });
    });
8
Jijo Paulose

nous pouvons stocker des données en session et les utiliser n'importe où dans notre programme.

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

Autre endroit

$scope.data = $window.sessionStorage.getItem("Mydata");
5
Alex Kumbhani

J'ai vu les réponses ici, et cela répond à la question du partage de données entre contrôleurs, mais que dois-je faire si je veux qu'un contrôleur informe l'autre du fait que les données ont été modifiées (sans utiliser broadcast)? FACILE! Juste en utilisant le célèbre motif de visiteur:

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

De cette manière simple, un contrôleur peut mettre à jour un autre contrôleur pour lequel certaines données ont été mises à jour.

4
Omri Lahav

J'ai créé une fabrique qui contrôle l'étendue partagée entre les modèles du chemin d'accès afin que vous puissiez conserver les données partagées au moment même où les utilisateurs naviguent dans le même chemin d'accès parent.

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

Ainsi, si l'utilisateur se connecte à un autre chemin, par exemple "/ Support", les données partagées du chemin "/ Client" seront automatiquement détruites. Mais si, au lieu de cela, l'utilisateur choisit des chemins "enfants", tels que "/ Client/1" ou "/ Client/liste", la portée ne sera pas détruite.

Vous pouvez voir un exemple ici: http://plnkr.co/edit/OL8of9

3
Oberdan Nunes

Je ne sais pas si cela aidera quelqu'un, mais, basé sur Charx (merci!), J'ai créé un service de cache simple. N'hésitez pas à utiliser, remixer et partager:

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

One way utilisant le service angulaire:

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/

2
Siva ganesh

Créez une fabrique dans votre module et ajoutez une référence à la fabrique dans le contrôleur, utilisez ses variables dans le contrôleur et obtenez maintenant la valeur des données dans un autre contrôleur en ajoutant une référence, où vous le souhaitez.

2
Resham Kadel

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

Au clic, vous pouvez appeler une méthode qui appelle une diffusion:

$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

One way utilisant le service angulaire:

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: ''};
});
2
Subhransu

Pour améliorer la solution proposée par @Maxim en utilisant $ broadcast, les données d'envoi ne changent pas

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

mais à l'écoute des données

$scope.$on('SOME_TAG', function(event, args) {
    console.log("My variable is", args);// args is value of your variable
})
1
Cedriga

FYI L'objet $ scope a $ emit, $ broadcast, $ on ET l'objet $ rootScope a l'identique $ emit, $ broadcast, $ on

en savoir plus sur le modèle de conception publier/souscrire en mode angulaire ici

1

Il y a trois façons de le faire,

a) utiliser un service

b) Exploiter la relation parent/enfant dépendante entre les portées du contrôleur.

c) Dans Angular 2.0 "Le mot" En tant que "transférera les données d'un contrôleur à un autre.

Pour plus d'informations avec exemple, s'il vous plaît vérifier le lien ci-dessous:

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

1
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'
}
}

Premier contrôleur

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

Deuxième contrôleur

 <div ng-controller="SecondController as vm">
    Second Controller<br>
    {{vm.data.value}}
</div>
0
testmeon