Kann ein AngularJS-Controller einen anderen anrufen?

581

Ist es möglich, dass ein Controller einen anderen verwendet?

Zum Beispiel:

Dieses HTML-Dokument druckt einfach eine vom MessageCtrlController übermittelte Nachricht in der messageCtrl.jsDatei.

<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>

Die Controller-Datei enthält den folgenden Code:

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

Welches druckt einfach das aktuelle Datum;

Wenn ich einen anderen Controller hinzufügen würde, DateCtrlder das Datum in einem bestimmten Format zurückgibt MessageCtrl, wie würde man das tun? Das DI-Framework scheint sich mit XmlHttpRequestsDiensten zu befassen und auf diese zuzugreifen.

BanksySan
quelle
4
In diesem Google-Gruppenthread, groups.google.com/d/topic/angular/m_mn-8gnNt4/discussion , werden fünf Möglichkeiten erläutert , wie Controller miteinander kommunizieren können.
Mark Rajcok
Hier gibt es bereits gute Antworten, daher möchte ich nur darauf hinweisen, dass für den genannten Anwendungsfall möglicherweise ein AngularJS-Filter eine bessere Lösung wäre. Ich dachte nur, ich würde es erwähnen :)
Joe Dyndale

Antworten:

705

Es gibt mehrere Möglichkeiten, zwischen Controllern zu kommunizieren.

Das Beste ist wahrscheinlich, einen Dienst zu teilen:

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
}

Ein anderer Weg ist das Aussenden eines Ereignisses zum Umfang:

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

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

In beiden Fällen können Sie auch mit jeder Direktive kommunizieren.

Vojta
quelle
4
Hia, das erste Beispiel würde erfordern, dass die Webseite alle Dienste im Stapel kennt. Was sich nach einem schlechten Geruch anfühlt (?). Müsste die Webseite nicht wie beim zweiten das Argument $ scope angeben?
BanksySan
54
Was? Warum? Alle Steuerungen werden von Angulars DI injiziert.
Vojta
7
@JoshNoe in 1 / Sie haben zwei Controller (oder mehr) und beide erhalten einen identischen / gemeinsam genutzten Dienst. Dann haben Sie mehrere Möglichkeiten zu kommunizieren, einige davon haben Sie erwähnt. Ich würde basierend auf Ihrem spezifischen Anwendungsfall entscheiden. Sie können die gemeinsam genutzte Logik / den gemeinsam genutzten Status in den Dienst einfügen, und beide Controller delegieren nur an diesen Dienst oder exportieren den Dienst sogar in die Vorlage. Natürlich kann der Dienst auch Ereignisse
auslösen
137
Kommen Sie zu spät: Ihr wisst, dass ihr mit THE Vojta von Google streitet, der an AngularJS arbeitet, oder? :)
Suman
16
Mir war nicht klar, dass der ereignisemittierende Controller in meinem HTML-Code ein untergeordneter Knoten des Listening-Controllers sein muss, damit er funktioniert.
Djangonaut
122

Siehe diese Geige: http://jsfiddle.net/simpulton/XqDxG/

Sehen Sie sich auch das folgende Video an: Kommunikation zwischen Controllern

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'];
Adardesign
quelle
12
Die obige Geige und das Video teilen sich einen Dienst. Hier ist eine Geige, die $ scope verwendet. $ Emit
Mark Rajcok
1
@adardesign: Ich würde gerne das gleiche prägnante und aussagekräftige Beispiel für Direktiven lesen (danke auch für diese Antwort!)
sscarduzio
Tolle Antwort, ich verwende myModule.service ('mySharedService', Funktion ($ rootScope) {}) anstelle von myModule.factory, aber es funktioniert trotzdem!
TacoEater
Ausgezeichnet. Ich habe jedoch eine Frage: Warum haben Sie einen Handler in ControllerZero hinzugefügt? $ scope. $ on ('handleBroadcast', function () {$ scope.message = sharedService.message;});
ZooZ
Das Video ist wirklich großartig! Es scheint, dass dies das ist, was ich brauche, um den Status eines anderen Controllers von einem anderen Controller abzufragen. Dies funktioniert jedoch nicht mit der Funktion "Aufrufen". Es funktioniert mit der Aktion "Auslösen". Wenn ein Controller eine Aktion ausführt und einen neuen Status hat, muss er den Status senden, und es liegt an anderen Controllern, diesen Broadcast anzuhören und entsprechend zu reagieren. Oder führen Sie die Aktion im gemeinsam genutzten Dienst aus und senden Sie den Status. Bitte sagen Sie mir, ob mein Verständnis korrekt ist.
Tarekahf
53

Wenn Sie einen Controller in einen anderen aufrufen möchten, stehen vier Methoden zur Verfügung

  1. $ rootScope. $ emit () und $ rootScope. $ Broadcast ()
  2. Wenn der zweite Controller untergeordnet ist, können Sie die untergeordnete untergeordnete Kommunikation verwenden.
  3. Verwenden Sie Dienste
  4. Art von Hack - mit Hilfe von angle.element ()

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

Der Controller und sein Bereich können zerstört werden, aber $ rootScope bleibt in der gesamten Anwendung erhalten. Aus diesem Grund verwenden wir $ rootScope, da $ rootScope allen Bereichen übergeordnet ist.

Wenn Sie eine Kommunikation zwischen Eltern und Kind durchführen und sogar das Kind mit seinen Geschwistern kommunizieren möchte, können Sie $ Broadcast verwenden

Wenn Sie eine Kommunikation vom Kind zum Elternteil durchführen und keine Geschwister beteiligt sind, können Sie $ rootScope. $ Emit verwenden

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

In der obigen Codekonsole von $ emit ruft 'childEmit' nicht innerhalb von untergeordneten Geschwistern auf und es wird nur innerhalb von Eltern aufgerufen, wobei $ Broadcast auch innerhalb von Geschwistern und Eltern aufgerufen wird. Dies ist der Ort, an dem die Leistung in eine Aktion einfließt. $ Emit ist Vorzuziehen, wenn Sie die Kommunikation zwischen Kind und Eltern verwenden, da einige schmutzige Überprüfungen übersprungen werden.

2. Wenn der zweite Controller untergeordnet ist, können Sie die untergeordnete übergeordnete Kommunikation verwenden

Dies ist eine der besten Methoden. Wenn Sie eine Kommunikation zwischen Eltern und Kindern durchführen möchten, bei der das Kind mit den unmittelbaren Eltern kommunizieren möchte, ist keine Übertragung oder Ausgabe erforderlich. Wenn Sie jedoch eine Kommunikation zwischen Eltern und Kindern durchführen möchten, müssen Sie dies tun Verwenden Sie entweder Service oder $ Broadcast

Zum Beispiel 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);
  });

Wenn Sie die Kommunikation zwischen Kind und Eltern verwenden, sucht Angularjs nach einer Variablen im Kind. Wenn sie im Inneren nicht vorhanden ist, werden die Werte im übergeordneten Controller angezeigt.

3.Verwenden Sie Dienste

AngularJS unterstützt die Konzepte der "Trennung von Bedenken" mithilfe der Dienstarchitektur . Services sind Javascript-Funktionen und nur für bestimmte Aufgaben verantwortlich. Dies macht sie zu einer einzelnen Entität, die gewartet und getestet werden kann. Services, die zum Injizieren mit dem Abhängigkeitsinjektions-Mekahnismus von Angularjs verwendet werden.

Angularjs Code:

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");
});

Es werden die Ausgaben Hello Child World und Hello Parent World ausgegeben. Gemäß Angular Docs of Services Singletons - Jede von einem Service abhängige Komponente erhält einen Verweis auf die einzelne Instanz, die von der Service Factory generiert wurde .

4. Art des Hacks - mit Hilfe von angle.element ()

Diese Methode ruft scope () vom Element ab, indem sie die ID / unique class.angular.element () -Methode zurückgibt. Scope () gibt die $ scope-Variable einer anderen Variablen unter Verwendung der $ scope-Variablen eines Controllers in einem anderen an. Dies ist keine gute Vorgehensweise.

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

Im obigen Code zeigen Controller ihren eigenen Wert in HTML an. Wenn Sie auf Text klicken, erhalten Sie entsprechende Werte in der Konsole. Wenn Sie auf den Bereich der übergeordneten Controller klicken, wird der Wert von child und umgekehrt vom Browser konsolidiert.

Shubham Nigam
quelle
52

Hier ist ein einseitiges Beispiel für zwei Controller, die Servicedaten gemeinsam nutzen:

<!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>

Auch hier: https://gist.github.com/3595424

exclsr
quelle
Und wenn theServiceUpdates durchgeführt werden thing.x, wird diese Änderung automatisch auf die <Eingaben> in FirstCtrlund übertragen SecondCtrl, oder? Und man kann auch thing.xdirekt über einen der beiden <Eingänge> wechseln (richtig?).
KajMagnus
4
Ja. Alle Angular-Dienste sind Anwendungs-Singletons, dh es gibt nur eine Instanz des Dienstes. Referenz: docs.angularjs.org/guide/dev_guide.services.creating_services
ohne
Der Link in meinem vorherigen Kommentar ist 404, daher hier der heutige Servicehandbuch, der
besagt
1
@exclsr Ja! Entschuldigung, das habe ich schon
mal
3
Mit Abstand das beste Beispiel, das ich bisher im Internet gesehen habe. Vielen Dank
Sevenearths
33

Wenn Sie Ereignisse senden und senden möchten, um Daten auszutauschen oder Funktionen zwischen Controllern anzurufen , sehen Sie sich bitte diesen Link an : und überprüfen Sie die Antwort mit zbynour(Antwort mit maximaler Stimmenzahl). Ich zitiere seine Antwort !!!

Wenn der Gültigkeitsbereich von firstCtrl dem Bereich von secondCtrl übergeordnet ist, sollte Ihr Code funktionieren, indem $ emit durch $ Broadcast in firstCtrl ersetzt wird:

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

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

Falls zwischen Ihren Bereichen keine Eltern-Kind-Beziehung besteht, können Sie $ rootScope in den Controller einfügen und das Ereignis an alle untergeordneten Bereiche (dh auch secondCtrl) senden.

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

Wenn Sie das Ereignis vom untergeordneten Controller an Bereiche nach oben senden müssen, können Sie $ scope. $ Emit verwenden. Wenn der Bereich von firstCtrl dem Bereich von secondCtrl übergeordnet ist:

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

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

Zwei weitere Geigen: (Non-Service-Ansatz)

1) Für Eltern-Kind-Controller - Verwendung $scopedes übergeordneten Controllers zum Senden / Senden von Ereignissen. http://jsfiddle.net/laan_sachin/jnj6y/

2) Verwendung $rootScopeüber nicht verwandte Controller hinweg. http://jsfiddle.net/VxafF/

Dunkler Ritter
quelle
Welcher Grund für all diese Komplexität bei Ereignissen? Warum nicht so etwas tun? jsfiddle.net/jnj6y/32
Dfr
Es hängt davon ab, welche Art von Eltern-Kind-Beziehung richtig ist. Es könnte sich um eine DOM-Hierarchie handeln, bei der Fallereignisse es Ihnen ermöglichen würden, Dinge zu entkoppeln.
DarkKnight
17

Die tatsächliche Verwendung von Emit und Broadcast ist ineffizient, da das Ereignis in der Bereichshierarchie auf und ab sprudelt, was für eine komplexe Anwendung leicht zu einer Leistungsminderung führen kann.

Ich würde vorschlagen, einen Dienst zu nutzen. So habe ich es kürzlich in einem meiner Projekte implementiert - https://gist.github.com/3384419 .

Grundidee - Registrieren Sie einen Pub-Sub- / Event-Bus als Service. Fügen Sie dann diesen Ereignisbus ein, wo immer Sie Ereignisse / Themen abonnieren oder veröffentlichen müssen.

numan salati
quelle
5

Ich kenne diesen Weg auch.

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

Aber ich benutze es nicht zu oft, weil ich jQuery-Selektoren nicht gerne im Winkelcode verwende.

Andrey Korchak
quelle
die beste Antwort. So einfach und leicht ... =)
zVictor
3
@zVictor, dies ist wirklich ein "letzter Ausweg" -Ansatz. Es funktioniert, aber es bricht aus dem Bereich aus, um Ihren Weg zurück zu erzwingen. Dies verwendet die DOM-Manipulation, um etwas zu erzwingen, anstatt es programmgesteuert zu tun. Es ist einfach, es funktioniert, aber es ist nicht skalierbar.
Brian Noah
2
@ BrianNoah, stimmt. Es ist in Ordnung, diesen Code für Prototypen oder einige Experimente zu verwenden, aber nicht für Produktionscode.
Andrey Korchak
1
Das ist das Schlimmste, was man tun kann. DOM-Manipulation in Diensten und direkter Zugriff auf den Bereich.
Mattia Franchetto
3

Es gibt eine Methode, die nicht von Diensten abhängig ist, $broadcastoder $emit. Es ist nicht in allen Fällen geeignet, aber wenn Sie zwei verwandte Controller haben, die in Direktiven abstrahiert werden können, können Sie die requireOption in der Direktivendefinition verwenden. Auf diese Weise kommunizieren ngModel und ngForm höchstwahrscheinlich. Sie können dies verwenden, um zwischen Direktiven-Controllern zu kommunizieren, die entweder verschachtelt sind oder sich auf demselben Element befinden.

Für eine Eltern / Kind-Situation wäre die Verwendung wie folgt:

<div parent-directive>
  <div inner-directive></div>
</div>

Und die wichtigsten Punkte, um es zum Laufen zu bringen: In der übergeordneten Direktive sollten Sie mit den aufzurufenden Methoden sie auf this(nicht auf $scope) definieren:

controller: function($scope) {
  this.publicMethodOnParentDirective = function() {
    // Do something
  }
}

In der Definition der untergeordneten Direktive können Sie die requireOption verwenden, damit der übergeordnete Controller an die Verknüpfungsfunktion übergeben wird (sodass Sie dann Funktionen aus scopeder untergeordneten Direktive aufrufen können .

require: '^parentDirective',
template: '<span ng-click="onClick()">Click on this to call parent directive</span>',
link: function link(scope, iElement, iAttrs, parentController) {
  scope.onClick = function() {
    parentController.publicMethodOnParentDirective();
  }
}

Das Obige kann unter http://plnkr.co/edit/poeq460VmQER8Gl9w8Oz?p=preview eingesehen werden

Eine Geschwisteranweisung wird ähnlich verwendet, aber beide Anweisungen beziehen sich auf dasselbe Element:

<div directive1 directive2>
</div>

Wird verwendet, indem eine Methode erstellt wird für directive1:

controller: function($scope) {
  this.publicMethod = function() {
    // Do something
  }
}

Und in Direktive2 kann dies mit der requireOption aufgerufen werden, die dazu führt, dass der siblingController an die Link-Funktion übergeben wird:

require: 'directive1',
template: '<span ng-click="onClick()">Click on this to call sibling directive1</span>',
link: function link(scope, iElement, iAttrs, siblingController) {
  scope.onClick = function() {
    siblingController.publicMethod();
  }
}

Dies kann unter http://plnkr.co/edit/MUD2snf9zvadfnDXq85w?p=preview eingesehen werden .

Die Verwendung davon?

  • Übergeordnet: Jeder Fall, in dem untergeordnete Elemente sich bei einem übergeordneten Element "registrieren" müssen. Ähnlich wie die Beziehung zwischen ngModel und ngForm. Diese können ein bestimmtes Verhalten hinzufügen, das sich auf Modelle auswirken kann. Möglicherweise haben Sie auch etwas rein DOM-basiertes, bei dem ein übergeordnetes Element die Positionen bestimmter untergeordneter Elemente verwalten muss, z. B. um das Scrollen zu verwalten oder darauf zu reagieren.

  • Geschwister: Ermöglichen, dass das Verhalten einer Direktive geändert wird. ngModel ist der klassische Fall, um der Verwendung von ngModel für Eingaben Parser / Validierung hinzuzufügen.

Michal Charemza
quelle
3

Ich weiß nicht, ob dies nicht den Standards entspricht, aber wenn Sie alle Ihre Controller in derselben Datei haben, können Sie Folgendes tun:

app = angular.module('dashboardBuzzAdmin', ['ngResource', 'ui.bootstrap']);

var indicatorsCtrl;
var perdiosCtrl;
var finesCtrl;

app.controller('IndicatorsCtrl', ['$scope', '$http', function ($scope, $http) {
  indicatorsCtrl = this;
  this.updateCharts = function () {
    finesCtrl.updateChart();
    periodsCtrl.updateChart();
  };
}]);

app.controller('periodsCtrl', ['$scope', '$http', function ($scope, $http) {
  periodsCtrl = this;
  this.updateChart = function() {...}
}]);

app.controller('FinesCtrl', ['$scope', '$http', function ($scope, $http) {
  finesCtrl = this;
  this.updateChart = function() {...}
}]);

Wie Sie sehen können, ruft IndikatorenCtrl beim Aufrufen von updateCharts die updateChart-Funktionen der beiden anderen Controller auf.

Tomascharad
quelle
2

Sie können den Dienst '$ controller' in Ihren übergeordneten Controller (MessageCtrl) einfügen und dann den untergeordneten Controller (DateCtrl) instanziieren / injizieren, indem Sie:
$scope.childController = $controller('childController', { $scope: $scope.$new() });

Jetzt können Sie von Ihrem untergeordneten Controller aus auf Daten zugreifen, indem Sie dessen Methoden aufrufen, da es sich um einen Dienst handelt.
Lassen Sie mich wissen, wenn ein Problem vorliegt.

Smrutiranjan Sahu
quelle
1

Das Folgende ist ein publish-subscribeAnsatz, der unabhängig von Angular JS ist.

Suche Param Controller

//Note: Multiple entities publish the same event
regionButtonClicked: function () 
{
        EM.fireEvent('onSearchParamSelectedEvent', 'region');
},

plantButtonClicked: function () 
{
        EM.fireEvent('onSearchParamSelectedEvent', 'plant');
},

Search Choices Controller

//Note: It subscribes for the 'onSearchParamSelectedEvent' published by the Search Param Controller
localSubscribe: function () {
        EM.on('onSearchParamSelectedEvent', this.loadChoicesView, this);

});


loadChoicesView: function (e) {

        //Get the entity name from eData attribute which was set in the event manager
        var entity = $(e.target).attr('eData');

        console.log(entity);

        currentSelectedEntity = entity;
        if (entity == 'region') {
            $('.getvalue').hide();
            this.loadRegionsView();
            this.collapseEntities();
        }
        else if (entity == 'plant') {
            $('.getvalue').hide();
            this.loadPlantsView();
            this.collapseEntities();
        }


});

Event Manager

myBase.EventManager = {

    eventArray:new Array(),


    on: function(event, handler, exchangeId) {
        var idArray;
        if (this.eventArray[event] == null) {
            idArray = new Array();
        } else { 
            idArray = this.eventArray[event];
        }
        idArray.push(exchangeId);
        this.eventArray[event] = idArray;

        //Binding using jQuery
        $(exchangeId).bind(event, handler);
    },

    un: function(event, handler, exchangeId) {

        if (this.eventArray[event] != null) {
            var idArray = this.eventArray[event];
            idArray.pop(exchangeId);
            this.eventArray[event] = idArray;

            $(exchangeId).unbind(event, handler);
        }
    },

    fireEvent: function(event, info) {
        var ids = this.eventArray[event];

        for (idindex = 0; idindex < ids.length; idindex++) {
            if (ids[idindex]) {

                //Add attribute eData
                $(ids[idindex]).attr('eData', info);
                $(ids[idindex]).trigger(event);
            }
        }
    }
};

Global

var EM = myBase.EventManager;
LCJ
quelle
1

In Winkel 1.5 kann dies wie folgt erreicht werden:

(function() {
  'use strict';

  angular
    .module('app')
    .component('parentComponent',{
      bindings: {},
      templateUrl: '/templates/products/product.html',
      controller: 'ProductCtrl as vm'
    });

  angular
    .module('app')
    .controller('ProductCtrl', ProductCtrl);

  function ProductCtrl() {
    var vm = this;
    vm.openAccordion = false;

    // Capture stuff from each of the product forms
    vm.productForms = [{}];

    vm.addNewForm = function() {
      vm.productForms.push({});
    }
  }

}());

Dies ist die übergeordnete Komponente. Hier habe ich eine Funktion erstellt, die ein anderes Objekt in mein productFormsArray schiebt - Hinweis - dies ist nur mein Beispiel, diese Funktion kann wirklich alles sein.

Jetzt können wir eine weitere Komponente erstellen, die Folgendes verwendet require:

(function() {
  'use strict';

  angular
    .module('app')
    .component('childComponent', {
      bindings: {},
      require: {
        parent: '^parentComponent'
      },
      templateUrl: '/templates/products/product-form.html',
      controller: 'ProductFormCtrl as vm'
    });

  angular
    .module('app')
    .controller('ProductFormCtrl', ProductFormCtrl);

  function ProductFormCtrl() {
    var vm = this;

    // Initialization - make use of the parent controllers function
    vm.$onInit = function() {
      vm.addNewForm = vm.parent.addNewForm;
    };  
  }

}());

Hier erstellt die untergeordnete Komponente einen Verweis auf die übergeordnete Komponentenfunktion, addNewFormdie dann an den HTML-Code gebunden und wie jede andere Funktion aufgerufen werden kann.

Katana24
quelle