Czy jeden kontroler AngularJS może wywoływać inny?


581

Czy jest możliwe, aby jeden kontroler używał innego?

Na przykład:

Ten dokument HTML po prostu drukuje wiadomość dostarczoną przez MessageCtrlkontroler w messageCtrl.jspliku.

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

Plik kontrolera zawiera następujący kod:

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

Który po prostu drukuje bieżącą datę;

Gdybym miał dodać kolejny kontroler, DateCtrlktóry wrócił do daty w określonym formacie MessageCtrl, jak by to zrobić? Ramy DI wydają się dotyczyć XmlHttpRequestsusług i uzyskiwać do nich dostęp.


4
Wątek grupy google, groups.google.com/d/topic/angular/m_mn-8gnNt4/discussion , omawia 5 sposobów, w jaki administratorzy mogą ze sobą rozmawiać.
Mark Rajcok,

Istnieją już dobre odpowiedzi, więc chciałbym tylko zauważyć, że w przypadku wspomnianego konkretnego przypadku zastosowania lepszym rozwiązaniem może być filtr AngularJS? Pomyślałem, że wspomnę o tym :)
Joe Dyndale

Odpowiedzi:


705

Istnieje wiele sposobów komunikacji między kontrolerami.

Najlepszym rozwiązaniem jest prawdopodobnie udostępnianie usługi:

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
}

Innym sposobem jest wysłanie zdarzenia w zakresie:

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

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

W obu przypadkach możesz również komunikować się z dowolną dyrektywą.


4
Hia, Pierwszy przykład wymagałby, aby strona była świadoma wszystkich usług na stosie. Co wydaje się być nieprzyjemnym zapachem (?). Podobnie jak w przypadku drugiej strony, czy strona nie musiałaby podawać argumentu $ scope?
BanksySan,

54
Co? Dlaczego? Wszystkie kontrolery są wstrzykiwane przez DI Angulara.
Vojta

7
@JoshNoe w 1 / masz dwa kontrolery (lub więcej) i oba otrzymują jedną identyczną / wspólną usługę. Następnie masz wiele sposobów komunikowania się, niektóre z nich wspomniałeś. Zdecydowałbym na podstawie konkretnego przypadku użycia. Możesz umieścić współdzieloną logikę / stan w usłudze, a oba kontrolery delegują tylko tę usługę, a nawet eksportują usługę do szablonu. Oczywiście usługa może również odpalać zdarzenia ...
Vojta

137
Przychodzisz tak późno: wiecie, że kłócisz się z THE Vojtą z Google, która pracuje na AngularJS, prawda? :)
Suman

16
Nie było dla mnie oczywiste, że w moim HTML kontroler emitujący zdarzenia musi być węzłem potomnym kontrolera nasłuchującego, aby działał.
djangonaut

122

Zobacz to skrzypce: http://jsfiddle.net/simpulton/XqDxG/

Obejrzyj także następujący film: Komunikacja między kontrolerami

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'];

12
Powyższe skrzypce i wideo udostępniają usługę. Oto skrzypce, które używają $ scope. $ Emit
Mark Rajcok

1
@adardesign: Z przyjemnością przeczytam ten sam zwięzły i znaczący przykład dla dyrektyw (dziękuję również za tę odpowiedź!)
sscarduzio

Świetna odpowiedź, używam myModule.service ('mySharedService', function ($ rootScope) {}) zamiast myModule.factory, ale mimo to działa!
TacoEater,

Świetny. Chociaż mam pytanie: dlaczego dodałeś moduł obsługi w ControllerZero? $ scope. $ on ('handleBroadcast', function () {$ scope.message = sharedService.message;});
ZooZ

Dostarczone wideo jest naprawdę niesamowite! Wydaje mi się, że właśnie o to muszę zapytać stan innego kontrolera od innego kontrolera. Nie działa to jednak przy użyciu funkcji „invoke”. Działa przy użyciu akcji „wyzwalacza”. Tak skutecznie, jeśli kontroler wykonuje akcję i ma nowy stan, będzie musiał nadać ten stan, a inne kontrolery będą słuchać tej transmisji i odpowiednio zareagować. Lub lepiej, wykonaj akcję w usłudze współdzielonej, a następnie wyemituj stan. Poinformuj mnie, czy rozumiem poprawnie.
tarekahf

53

Jeśli chcesz połączyć jeden kontroler z innym, dostępne są cztery metody

  1. $ rootScope. $ emit () i $ rootScope. $ broadcast ()
  2. Jeśli drugim kontrolerem jest dziecko, możesz skorzystać z nadrzędnej komunikacji podrzędnej.
  3. Skorzystaj z usług
  4. Rodzaj hacka - za pomocą angular.element ()

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

Kontroler i jego zakres mogą zostać zniszczone, ale $ rootScope pozostaje w aplikacji, dlatego bierzemy $ rootScope, ponieważ $ rootScope jest rodzicem wszystkich zakresów.

Jeśli prowadzisz komunikację między rodzicem a dzieckiem, a nawet dziecko chce komunikować się z rodzeństwem, możesz użyć programu $ broadcast

Jeśli wykonujesz komunikację między dzieckiem a rodzicem, żadne rodzeństwo nie jest powiązane, możesz użyć $ rootScope.

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>

Kod Angularjs

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

W powyższej kodzie konsoli $ emit „childEmit” nie będzie wywoływał rodzeństwa podrzędnego i będzie wywoływał tylko rodzica, gdzie $ broadcast zostanie wywołany również wewnątrz rodzeństwa i rodzica. To jest miejsce, w którym występuje wydajność. preferowane, jeśli używasz komunikacji dziecko-rodzic, ponieważ pomija ona niektóre brudne kontrole.

2. Jeśli drugi kontroler jest dzieckiem, możesz użyć komunikacji Dziecko-rodzic

Jest to jedna z najlepszych metod. Jeśli chcesz przeprowadzić komunikację między rodzicem a dzieckiem, w której dziecko chce komunikować się z bezpośrednim rodzicem , nie potrzebuje żadnej emisji lub emisji, ale jeśli chcesz nawiązać komunikację między rodzicem a dzieckiem, musisz użyj usługi lub $ broadcast

Na przykład 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);
  });

Za każdym razem, gdy używasz komunikacji dziecko-rodzic, Angularjs szuka zmiennej wewnątrz dziecka, jeśli nie jest ona obecna w środku, wybierze wyświetlanie wartości w kontrolerze nadrzędnym.

3.Korzystaj z usług

AngularJS obsługuje koncepcje „oddzielania obaw” przy użyciu architektury usług. Usługi są funkcjami javascript i są odpowiedzialne za wykonywanie tylko określonych zadań, co czyni je indywidualnymi jednostkami, które można konserwować i testować .

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

Daje wyjście Hello Child World i Hello Parent World. Według dokumentów Angular usług Singletons - Każdy komponent zależny od usługi otrzymuje odniesienie do pojedynczego wystąpienia wygenerowanego przez fabrykę usług .

4. Rodzaj hacka - za pomocą angular.element ()

Ta metoda pobiera zakres () z elementu za pomocą swojej metody Id / unique class.angular.element () zwraca element, a scope () daje zmienną $ scope innej zmiennej przy użyciu zmiennej $ scope jednego kontrolera wewnątrz drugiego, nie jest dobrą praktyką.

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

W powyższym kodzie kontrolery wyświetlają swoją wartość na HTML, a kiedy klikniesz tekst, otrzymasz odpowiednio wartości w konsoli. Jeśli klikniesz na zakres kontrolerów nadrzędnych, przeglądarka konsoluje wartość child i viceversa.


52

Oto jednostronicowy przykład dwóch kontrolerów współdzielących dane usługi:

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

Również tutaj: https://gist.github.com/3595424


A jeśli theServiceaktualizacje thing.x, to ta zmiana automatycznie sugeruje <wejście> w FirstCtrli SecondCtrl, prawda? I można również zmienić thing.xbezpośrednio za pomocą jednego z dwóch <wejść> (prawda?).
KajMagnus

4
Tak. Wszystkie usługi Angular są singletonami aplikacji, co oznacza, że ​​istnieje tylko jedna instancja Usługi. Odniesienie: docs.quarejs.org/guide/dev_guide.services.creating_services
dotyczy

Link w moim poprzednim komentarzu to 404, więc oto przewodnik po usługach, dziś, że usługi notatek są singletonami: docs.quarejs.org/guide/services
excl.

1
@exclsr Tak! Przepraszam, że tęskniłem wcześniej
CodyBugstein

3
Zdecydowanie najlepszy przykład, jaki do tej pory widziałem w Internecie. Dziękuję
Sevenearths,

33

Jeśli chcesz emitować i transmitować zdarzenia w celu udostępniania danych lub funkcji połączeń między kontrolerami , spójrz na ten link : i sprawdź odpowiedź przez zbynour(odpowiedz z maksymalną liczbą głosów). Cytuję jego odpowiedź !!!

Jeśli zakres firstCtrl jest nadrzędny dla zakresu secondCtrl, kod powinien działać, zastępując $ emit przez $ broadcast w firstCtrl:

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

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

Jeśli pomiędzy Twoimi zasięgami nie ma relacji rodzic-dziecko, możesz wstrzyknąć $ rootScope do kontrolera i transmitować zdarzenie do wszystkich zakresów potomnych (tj. Także secondCtrl).

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

Wreszcie, gdy trzeba wysłać zdarzenie z kontrolera potomnego w zakresy w górę, możesz użyć $ scope. $ Emit. Jeśli zakres firstCtrl jest rodzicem zakresu secondCtrl:

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

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

24

Dwa kolejne skrzypce: (podejście nieobsługowe)

1) Dla kontrolera $scopenadrzędnego i podrzędnego - Wykorzystanie nadrzędnego kontrolera do emisji / emisji zdarzeń. http://jsfiddle.net/laan_sachin/jnj6y/

2) Korzystanie $rootScopez niepowiązanych kontrolerów. http://jsfiddle.net/VxafF/


Jaki jest powód tej złożoności wydarzeń? Dlaczego nie zrobić czegoś takiego? jsfiddle.net/jnj6y/32
DFR

To zależy od tego, jaki rodzaj relacji rodzic-dziecko jest odpowiedni. Może to być heirarchia DOM, jeśli zdarzenia przypadków pozwolą ci oddzielić rzeczy.
DarkKnight

17

W rzeczywistości użycie emisji i emisji jest nieefektywne, ponieważ zdarzenie przesuwa się w górę iw dół hierarchii zasięgu, co może łatwo zmienić się w butelkę wydajności dla złożonej aplikacji.

Sugerowałbym skorzystanie z usługi. Oto jak niedawno wdrożyłem go w jednym z moich projektów - https://gist.github.com/3384419 .

Podstawowy pomysł - zarejestruj autobus sub-pub / event jako usługę. Następnie wstrzyknij tę magistralę zdarzeń tam, gdzie trzeba subskrybować lub opublikować wydarzenia / tematy.


5

Znam również tę drogę.

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

Ale nie używam go zbyt często, ponieważ nie lubię używać selektorów jQuery w kodzie kątowym.


najlepsza odpowiedź. Tak proste i łatwe ... =)
zVictor

3
@ zVictor, jest to naprawdę podejście typu „ostateczność”. Działa, ale wychodzi poza zakres, aby zmusić cię do powrotu. To używa manipulacji DOM, aby wymusić coś do zrobienia zamiast programowo. To proste, działa, ale nie jest skalowalne.
Brian Noah,

2
@BrianNoah, true. Można używać tego kodu do prototypów lub niektórych eksperymentów, ale nie do kodu produkcyjnego.
Andrey Korchak,

1
To najgorsze, co można zrobić. Manipulowanie DOM w usługach i bezpośredni dostęp do zakresu.
Mattia Franchetto,

3

Istnieje metoda niezależna od usług $broadcastlub $emit. Nie jest to odpowiednie we wszystkich przypadkach, ale jeśli masz 2 powiązane kontrolery, które można przekształcić w dyrektywy, możesz skorzystać z requireopcji w definicji dyrektywy. Jest to najprawdopodobniej sposób, w jaki komunikują się ngModel i ngForm. Możesz użyć tego do komunikacji między kontrolerami dyrektywy, które są zagnieżdżone lub w tym samym elemencie.

W przypadku sytuacji rodzic / dziecko użycie byłoby następujące:

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

I główne punkty, aby to działa: W dyrektywie macierzystego z metody nazywać, należy je określić na this(nie $scope):

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

W definicji dyrektywy podrzędnej można użyć tej requireopcji, aby nadrzędny kontroler został przekazany do funkcji dowiązania (aby można było wywoływać na niej funkcje z scopedyrektywy podrzędnej.

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

Powyższe można zobaczyć na stronie http://plnkr.co/edit/poeq460VmQER8Gl9w8Oz?p=preview

Dyrektywa dotycząca rodzeństwa jest stosowana podobnie, ale obie dyrektywy dotyczą tego samego elementu:

<div directive1 directive2>
</div>

Używane, tworząc metodę na directive1:

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

A w dyrektywie2 można to wywołać za pomocą requireopcji, która powoduje przekazanie kontrolera siblingController do funkcji link:

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

Można to zobaczyć na stronie http://plnkr.co/edit/MUD2snf9zvadfnDXq85w?p=preview .

Zastosowania tego?

  • Rodzic: każdy przypadek, w którym elementy potomne muszą się „zarejestrować” u rodzica. Podobnie jak związek między ngModel i ngForm. Mogą dodać pewne zachowanie, które może wpływać na modele. Możesz mieć również coś opartego wyłącznie na DOM, w którym element nadrzędny musi zarządzać pozycjami niektórych dzieci, powiedzmy, aby zarządzać przewijaniem lub reagować na nie.

  • Rodzeństwo: zezwalanie na modyfikację zachowania dyrektywy. ngModel to klasyczny przypadek dodawania parserów / sprawdzania poprawności do użycia ngModel na wejściach.


3

Nie wiem, czy jest to niezgodne ze standardami, ale jeśli masz wszystkie kontrolery w tym samym pliku, możesz zrobić coś takiego:

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

Jak widać wskaźnikiCtrl wywołuje funkcje updateChart pozostałych kontrolerów podczas wywoływania updateCharts.


2

Możesz wstrzyknąć usługę „$ controller” do kontrolera nadrzędnego (MessageCtrl), a następnie utworzyć instancję / wstrzyknąć kontroler podrzędny (DateCtrl), używając:
$scope.childController = $controller('childController', { $scope: $scope.$new() });

Teraz możesz uzyskać dostęp do danych z kontrolera podrzędnego, wywołując jego metody, ponieważ jest to usługa.
Daj mi znać, jeśli jakiś problem.


1

Poniżej znajduje się publish-subscribepodejście, które jest niezależne od Angular JS.

Wyszukaj Param Controller

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

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

Kontroler wyboru wyszukiwania

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


});

Menedżer zdarzeń

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

Światowy

var EM = myBase.EventManager;

1

W wersji kątowej 1.5 można to zrobić, wykonując następujące czynności:

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

}());

To jest element nadrzędny. W tym utworzyłem funkcję, która wypycha inny obiekt do mojej productFormstablicy - uwaga - to tylko mój przykład, ta funkcja może być czymkolwiek naprawdę.

Teraz możemy stworzyć kolejny komponent, który będzie wykorzystywał 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;
    };  
  }

}());

W tym przypadku komponent potomny tworzy odwołanie do funkcji komponentu nadrzędnego, addNewFormktóra może być następnie powiązana z kodem HTML i wywołana jak każda inna funkcja.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.