Question Un contrôleur AngularJS peut-il en appeler un autre?


Est-il possible d'avoir un contrôleur en utiliser un autre?

Par exemple:

Ce document HTML imprime simplement un message délivré par le MessageCtrl contrôleur dans le messageCtrl.js fichier.

<html xmlns:ng="http://angularjs.org/">
<head>
    <meta charset="utf-8" />
    <title>Inter Controller Communication</title>
</head>
<body>
    <div ng:controller="MessageCtrl">
        <p>{{message}}</p>
    </div>

    <!-- Angular Scripts -->
    <script src="http://code.angularjs.org/angular-0.9.19.js" ng:autobind></script>
    <script src="js/messageCtrl.js" type="text/javascript"></script>
</body>
</html>

Le fichier du contrôleur contient le code suivant:

function MessageCtrl()
{
    this.message = function() { 
        return "The current date is: " + new Date().toString(); 
    };
}

Qui imprime simplement la date actuelle;

Si je devais ajouter un autre contrôleur, DateCtrl qui a remis la date dans un format spécifique à MessageCtrl, comment irait-on faire ça? Le cadre DI semble être concerné par XmlHttpRequests et l'accès aux services.


549
2018-02-15 12:31


origine


Réponses:


Il y a plusieurs façons de communiquer entre les contrôleurs.

Le meilleur est probablement le partage d'un service:

function FirstController(someDataService) 
{
  // use the data service, bind to template...
  // or call methods on someDataService to send a request to server
}

function SecondController(someDataService) 
{
  // has a reference to the same instance of the service
  // so if the service updates state for example, this controller knows about it
}

Une autre manière est d'émettre un événement sur la portée:

function FirstController($scope) 
{
  $scope.$on('someEvent', function(event, args) {});
  // another controller or even directive
}

function SecondController($scope) 
{
  $scope.$emit('someEvent', args);
}

Dans les deux cas, vous pouvez également communiquer avec n'importe quelle directive.


680
2018-02-23 05:59



Voir ce violon: http://jsfiddle.net/simpulton/XqDxG/

Regardez aussi la vidéo suivante: Communication entre contrôleurs

Html:

<div ng-controller="ControllerZero">
  <input ng-model="message" >
  <button ng-click="handleClick(message);">LOG</button>
</div>

<div ng-controller="ControllerOne">
  <input ng-model="message" >
</div>

<div ng-controller="ControllerTwo">
  <input ng-model="message" >
</div>

javascript:

var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
  var sharedService = {};

  sharedService.message = '';

  sharedService.prepForBroadcast = function(msg) {
    this.message = msg;
    this.broadcastItem();
  };

  sharedService.broadcastItem = function() {
    $rootScope.$broadcast('handleBroadcast');
  };

  return sharedService;
});

function ControllerZero($scope, sharedService) {
  $scope.handleClick = function(msg) {
    sharedService.prepForBroadcast(msg);
  };

  $scope.$on('handleBroadcast', function() {
    $scope.message = sharedService.message;
  });        
}

function ControllerOne($scope, sharedService) {
  $scope.$on('handleBroadcast', function() {
    $scope.message = 'ONE: ' + sharedService.message;
  });        
}

function ControllerTwo($scope, sharedService) {
  $scope.$on('handleBroadcast', function() {
    $scope.message = 'TWO: ' + sharedService.message;
  });
}

ControllerZero.$inject = ['$scope', 'mySharedService'];        

ControllerOne.$inject = ['$scope', 'mySharedService'];

ControllerTwo.$inject = ['$scope', 'mySharedService'];

119
2017-08-07 13:40



Voici un exemple d'une page de deux contrôleurs partageant des données de service:

<!doctype html>
<html ng-app="project">
<head>
    <title>Angular: Service example</title>
    <script src="http://code.angularjs.org/angular-1.0.1.js"></script>
    <script>
var projectModule = angular.module('project',[]);

projectModule.factory('theService', function() {  
    return {
        thing : {
            x : 100
        }
    };
});

function FirstCtrl($scope, theService) {
    $scope.thing = theService.thing;
    $scope.name = "First Controller";
}

function SecondCtrl($scope, theService) {   
    $scope.someThing = theService.thing; 
    $scope.name = "Second Controller!";
}
    </script>
</head>
<body>  
    <div ng-controller="FirstCtrl">
        <h2>{{name}}</h2>
        <input ng-model="thing.x"/>         
    </div>

    <div ng-controller="SecondCtrl">
        <h2>{{name}}</h2>
        <input ng-model="someThing.x"/>             
    </div>
</body>
</html>

Ici aussi: https://gist.github.com/3595424


52
2017-09-02 06:51



Si vous voulez appeler un contrôleur dans un autre, il existe quatre méthodes disponibles

  1. $ rootScope. $ emit () et $ rootScope. $ broadcast ()
  2. Si le deuxième contrôleur est enfant, vous pouvez utiliser la communication parent-enfant.
  3. Utiliser les services
  4. Type de piratage - avec l'aide de angular.element ()

1. $ rootScope. $ Emit () et $ rootScope. $ Broadcast ()

Le contrôleur et sa portée peuvent être détruits, mais le $ rootScope reste à travers l'application, c'est pourquoi nous prenons $ rootScope car $ rootScope est parent de toutes les étendues.

Si vous effectuez une communication de parent à enfant et que même un enfant veut communiquer avec ses frères et sœurs, vous pouvez utiliser $ broadcast

Si vous effectuez une communication de l'enfant vers le parent, aucun frère et sœur n'est invité alors vous pouvez utiliser $ rootScope. $ Emit

HTML

<body ng-app="myApp">
    <div ng-controller="ParentCtrl" class="ng-scope">
      // ParentCtrl
      <div ng-controller="Sibling1" class="ng-scope">
        // Sibling first controller
      </div>
      <div ng-controller="Sibling2" class="ng-scope">
        // Sibling Second controller
        <div ng-controller="Child" class="ng-scope">
          // Child controller
        </div>
      </div>
    </div>
</body>

Angularjs Code

 var app =  angular.module('myApp',[]);//We will use it throughout the example 
    app.controller('Child', function($rootScope) {
      $rootScope.$emit('childEmit', 'Child calling parent');
      $rootScope.$broadcast('siblingAndParent');
    });

app.controller('Sibling1', function($rootScope) {
  $rootScope.$on('childEmit', function(event, data) {
    console.log(data + ' Inside Sibling one');
  });
  $rootScope.$on('siblingAndParent', function(event, data) {
    console.log('broadcast from child in parent');
  });
});

app.controller('Sibling2', function($rootScope) {
  $rootScope.$on('childEmit', function(event, data) {
    console.log(data + ' Inside Sibling two');
  });
  $rootScope.$on('siblingAndParent', function(event, data) {
    console.log('broadcast from child in parent');
  });
});

app.controller('ParentCtrl', function($rootScope) {
  $rootScope.$on('childEmit', function(event, data) {
    console.log(data + ' Inside parent controller');
  });
  $rootScope.$on('siblingAndParent', function(event, data) {
    console.log('broadcast from child in parent');
  });
});

Dans le code ci-dessus, la console de $ emit 'childEmit' n'appelle pas à l'intérieur des enfants et n'appelle qu'à l'intérieur de parent, où $ broadcast est appelée à l'intérieur des frères et soeurs et des parents.C'est l'endroit où les performances entrent dans une action. préférable, si vous utilisez la communication de l'enfant à l'autre parce que cela saute des contrôles sales.

2. Si le deuxième contrôleur est enfant, vous pouvez utiliser la communication parent enfant

C'est l'une des meilleures méthodes, si vous voulez faire communication parent-enfant où l'enfant veut communiquer avec parent immédiat alors il n'aurait pas besoin de $ broadcast ou de $ emit, mais si vous voulez faire une communication de parent à enfant, alors vous devez utiliser soit le service, soit $ broadcast

Par exemple HTML: -

<div ng-controller="ParentCtrl">
 <div ng-controller="ChildCtrl">
 </div>
</div>

Angularjs

 app.controller('ParentCtrl', function($scope) {
   $scope.value='Its parent';
      });
  app.controller('ChildCtrl', function($scope) {
   console.log($scope.value);
  });

Chaque fois que vous utilisez une communication enfant à parent, Angularjs va rechercher une variable à l'intérieur de l'enfant, Si elle n'est pas présente à l'intérieur, elle choisira de voir les valeurs dans le contrôleur parent.

3.Utiliser les services

AngularJS soutient les concepts de "Séparation des préoccupations" en utilisant l'architecture de services. Les services sont des fonctions javascript et sont responsables d'effectuer des tâches spécifiques uniquement. Cela en fait un entité individuelle lequel est maintenable et testable.Services utilisés pour injecter en utilisant le mecahnism d'injection de dépendance d'Angularjs.

Code Angularjs:

app.service('communicate',function(){
  this.communicateValue='Hello';
});

app.controller('ParentCtrl',function(communicate){//Dependency Injection
  console.log(communicate.communicateValue+" Parent World");
});

app.controller('ChildCtrl',function(communicate){//Dependency Injection
  console.log(communicate.communicateValue+" Child World");
});

Il donnera la sortie Hello Child World et Hello Parent World. Selon Angular docs de services Singletons - Chaque composant dépendant d'un service obtient une référence à l'instance unique générée par l'atelier de service.

4.Kind de pirater - avec l'aide de angular.element ()

Cette méthode obtient scope () de l'élément par sa méthode Id / unique class.angular.element () renvoie element et scope () donne $ variable d'une autre variable en utilisant la variable $ scope d'un contrôleur dans un autre n'est pas une bonne pratique.

HTML: -

<div id='parent' ng-controller='ParentCtrl'>{{varParent}}
 <span ng-click='getValueFromChild()'>Click to get ValueFormChild</span>
 <div id='child' ng-controller='childCtrl'>{{varChild}}
   <span ng-click='getValueFromParent()'>Click to get ValueFormParent </span>
 </div>
</div>

Angularjs: -

app.controller('ParentCtrl',function($scope){
 $scope.varParent="Hello Parent";
  $scope.getValueFromChild=function(){
  var childScope=angular.element('#child').scope();
  console.log(childScope.varChild);
  }
});

app.controller('ChildCtrl',function($scope){
 $scope.varChild="Hello Child";
  $scope.getValueFromParent=function(){
  var parentScope=angular.element('#parent').scope();
  console.log(parentScope.varParent);
  }
}); 

Dans le code ci-dessus les contrôleurs montrent leur propre valeur sur Html et quand vous cliquerez sur le texte vous obtiendrez des valeurs dans la console en conséquence. Si vous cliquez sur l'envergure des contrôleurs parent, le navigateur contiendra la valeur de l'enfant et viceversa.


46
2017-07-17 06:17



Si vous souhaitez émettre et diffuser des événements pour partager des données ou des fonctions d'appel entre les contrôleurs, regarde s'il te plaît lien: et vérifiez la réponse par zbynour (répondre avec le maximum de votes). Je cite sa réponse !!!

Si la portée de firstCtrl est parent de la portée secondCtrl, votre code devrait fonctionner en remplaçant $ emit par $ broadcast dans firstCtrl:

function firstCtrl($scope){
    $scope.$broadcast('someEvent', [1,2,3]);
}

function secondCtrl($scope){
    $scope.$on('someEvent', function(event, mass) {console.log(mass)});
}

Dans le cas où il n'y a pas de relation parent-enfant entre vos étendues, vous pouvez injecter $ rootScope dans le contrôleur et diffuser l'événement à toutes les portées enfant (c'est-à-dire aussi secondCtrl).

function firstCtrl($rootScope){
    $rootScope.$broadcast('someEvent', [1,2,3]);
}

Enfin, lorsque vous devez envoyer l'événement du contrôleur enfant vers les portées vers le haut, vous pouvez utiliser $ scope. $ Emit. Si portée de firstCtrl est parent de la portée secondCtrl:

function firstCtrl($scope){
    $scope.$on('someEvent', function(event, data) { console.log(data); });
}

function secondCtrl($scope){
    $scope.$emit('someEvent', [1,2,3]);
}

31
2017-10-15 13:26



Deux autres violons: (approche non-service)

1) Pour le contrôleur parent-enfant - Utilisation $scope du contrôleur parent pour émettre / diffuser des événements.       http://jsfiddle.net/laan_sachin/jnj6y/

2) Utilisation $rootScope à travers les contrôleurs non liés.       http://jsfiddle.net/VxafF/


24
2017-10-07 17:07



En fait, l'utilisation d'émission et de diffusion est inefficace car l'événement fait des bulles dans la hiérarchie de la portée, ce qui peut facilement se dégrader en performance de mise en bouteille pour une application complexe.

Je suggère d'utiliser un service. Voici comment je l'ai récemment mis en œuvre dans l'un de mes projets - https://gist.github.com/3384419.

Idée de base - enregistrer un bus pub-sub / événement en tant que service. Ensuite, injectez ce bus d'événements là où vous devez vous abonner ou publier des événements / sujets.


16
2017-08-18 04:32



Je connais aussi de cette façon.

angular.element($('#__userProfile')).scope().close();

Mais je ne m'en sers pas trop, car je n'aime pas utiliser les sélecteurs jQuery en code angulaire.


3
2017-07-16 13:45