Partager des propriétés avec AngularJS

J’ai cherché un petit moment comment partager des propriétés entre deux controllers, tout en observant leur valeur afin d’exécuter une action lors de modification. N’ayant pas trouvé de ressource compréhensible sur ce sujet, j’ai tenté de chercher par moi-même avec quelques essais.

Concernant le partage il semble évident qu’une solution propre doit passer par un service ou factory, qui peuvent facilement être injectés dans les controller. J’ai donc choisi l’approche du service qui me semble simple et efficace.

Le problème résidait plutôt dans l’observateur qui devait se trouver dans chaque controller. J’ai donc du le mettre dans un scope afin d’utiliser la fonction $watch d’AngularJS.

Voici ci-dessous la solution que j’ai trouvé et qui fonctionne. Préférant passer par le « controller as » plutôt que par le scope (Angular 1.2+), j’ai quand même cherché une autre manière de faire.

Le code

index.html

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body data-ng-app="myApp">
    <div class="container">
      <h1>Sandbox</h1>

      <section data-ng-controller="controller1">
        <div>
          <label>multiplicator</label>
          <input type="number"  data-ng-model="multiplicator"/>
        </div>
        <h2>Operation 1</h2>
          <p>
            <label>base</label>
            <input type="number" data-ng-model="base"/>
          </p>
          <p>{{base}} * {{multiplicator}} = {{result}}</p>
      </section>     

      <section data-ng-controller="controller2">
        <h2>Operation 2</h2>
          <p>
            <label>base</label>
            <input type="number" data-ng-model="base"/>
          </p>
          <p>{{base}} * {{srv.multiplicator}} = {{result}}</p>
      </section>
    </div>

    <script src="lib/angular.min.js"></script>
    <script src="scripts/app.js"></script>
    <script src="scripts/services/srvSharedProps.js"></script>
    <script src="scripts/controllers/ctrl1.js"></script>
    <script src="scripts/controllers/ctrl2.js"></script>
  </body>
</html>

srvSharedProps.js

Ce service permet l’accès aux propriétés partagées par les deux contrôleurs. Ici une seule valeur y est déclarée, mais on pourrait imaginer partager plusieurs objets avec leurs propres getter/setter.

myApp.service('sharedProps', function(){
    var that=this;
    this.multiplicator = 1;
    this.setMultiplicator = function(number){
        that.multiplicator = number;
    };
    this.getMultiplicator = function(){
        return that.multiplicator;
    };
});

ctrl1.js

est le contrôleur de la première zone de calcul. Lors d’un changement, elle met à jour l’élément partagés et recalcule le tout en fonction de l’observateur en cas de changement.

myApp.controller('controller1', ['$scope', 'sharedProps', function($scope, sharedProps){
    $scope.base = 4;
    $scope.result = 0;
    $scope.multiplicator = 1;

    $scope.setMultiplicator = function(number){
        sharedProps.setMultiplicator(number);
    };
    $scope.getMultiplicator = function(){
        sharedProps.getMultiplicator();
    };

    $scope.calculate = function(){
        $scope.result = $scope.base * $scope.multiplicator;
    };

    $scope.$watch("base", function(newValue, oldValue) {
        $scope.calculate();
    });

    $scope.$watch("multiplicator", function(newValue, oldValue) {
        sharedProps.setMultiplicator(newValue);
        $scope.calculate();
    });
}]);

ctrl2.js

Est le contrôleur de la deuxième zone de calcul. fonctionne comme le premier contrôleur.

myApp.controller('controller2', ['$scope', 'sharedProps', function($scope, sharedProps){
    $scope.base = 8;
    $scope.result = 0;
    $scope.srv = sharedProps;

    $scope.calculate = function(){
        $scope.result = $scope.base * sharedProps.multiplicator;
    };

    $scope.$watch('srv.multiplicator', function(newValue, oldValue) {
        $scope.calculate();
    });

    $scope.$watch('base', function(newValue, oldValue) {
        $scope.calculate();
    });
}]);

Je suis tombé sur cet article très intéressant qui répond au final à toutes les problématiques de ce cas, mais sans passer par les scope :

Five guidelines for avoiding scope soup

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

code