2015-10-19 18 views
7

Jestem świadomy, jak mogę uzyskać kontroler nadrzędny directive w funkcji link dyrektywy dotyczącej dziecka.
Jednak wolałbym nie używać funkcji link (i $scope razem) i mieć cały mój kod pod funkcją controller dyrektywy.Angular - uzyskaj kontrolkę dyrektywy nadrzędnej w kontrolerze podrzędnej (nie funkcji łącza)

angular.directive('parent', function(){ 
    return { 
     templateUrl: '/parent.html', 
     scope: true, 
     bindToController: true, 
     controllerAs: 'parentCtrl', 
     controller: function(){ 
      this.coolFunction = function(){ 
       console.log('cool'); 
      } 
     } 
    } 
}); 

angular.directive('child', function(){ 
    return { 
     templateUrl: '/child.html', 
     require: '^parent', 
     scope: true, 
     bindToController: true, 
     controllerAs: 'childCtrl', 
     controller: function() { 
      // I want to run coolFunction here. 
      // How do I do it? 
     } 
    } 
}); 

Każda pomoc jest doceniana!

+0

U chcą uniknąć za pomocą linku? Czemu? –

+0

Chciałbym napisać kod w sposób przyjazny dla Angular2. – Dmitry

+0

@Dmitry Trzymanie się kontrolerów i jqlite (jak poprawnie sugeruje odpowiedź) spowoduje, że twój kod będzie wrogi do Angular 2 (co jest przeciwieństwem przyjaznego). – estus

Odpowiedz

1

Można wstrzyknąć „$ element” do kontrolera i dostępu do kontrolera nadrzędnego podobnego -

controller: ($element) -> 
    var parentCtrl = $element.parent().controller('parent'); 
    parentCtrl.coolFunction(); 
    //.......... 
    //.......... 

To nie może być jak najbardziej przejrzysty sposób dostępu „any” kontrolera nadrzędnego, ponieważ wymaga specyficznej nazwy dyrektywy i jest jqlite, a nie czysty Angular.

Znaleziony ten wątek przydatny - How to access parent directive's controller by requiring it recursively?

EDIT: Dzięki @Dmitry na zastanawianie się, że kątowy nie potrzebuje „.parent”, aby uzyskać sterownik. Zaktualizowany kod -

controller: ($element) -> 
    var parentCtrl = $element.controller('parent'); 
    parentCtrl.coolFunction(); 
    //.......... 
+0

, która zbliża się do pożądanej funkcjonalności. Jedyną rzeczą, z której nie jestem zadowolony, jest część '$ element.parent()', ponieważ dziecko może nie być bezpośrednim dzieckiem rodzica, ale może być głębokie na kilka poziomów. Przypuszczam, że mógłbym wykonać sprawdzanie rekursywne dla atrybutu 'parent' w jakiś sposób – Dmitry

+0

@Dmitry - Nie jestem też fanem używania referencji 'parent'. Mam nadzieję, że istnieje bardziej elegancki sposób. – FrailWords

+0

Doceniam twoją pomoc. Z pewnością sprawił, że spojrzałem we właściwym kierunku. Po zbadaniu [kodu źródłowego Angulara] (https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L2005-L2042) wydaje się, że wywołanie '.parent' nie jest konieczne . Tak naprawdę to wypróbowałem i zadziałało bez '.parent'. Zaktualizuj swoją odpowiedź, a oznaczę ją jako zaakceptowaną. – Dmitry

4

Prawidłowe wzór byłoby

app.directive('child', function(){ 
    return { 
     templateUrl: '/child.html', 
     require: ['child', '^parent'], 
     scope: true, 
     bindToController: true, 
     controllerAs: 'childCtrl', 
     controller: function() { 
      this.coolFunction = function() { 
       this._parent.coolFunction(); 
      } 
     }, 
     link: function (scope, element, attrs, ctrls) { 
      var childCtrl = ctrls[0]; 
      var parentCtrl = ctrls[1]; 
      childCtrl._parent = parentCtrl; 
     } 
    } 
}); 

Złą rzeczą jest to, że _parent jest narażony na zakres z controllerAs, ale to rzadko być problemem.

Należy zauważyć, że nie będziesz mieć dostępu do kontrolera nadrzędnego od dziecka do momentu sklejenia go ze sobą przez link. Co jest w porządku, o ile korzystasz z kontrolera nadrzędnego w metodach potomnych.

Kontroler zapewnia metody i właściwości początkowe do przeglądania modelu (i robi to czystsze z kontrolerami), łącze skleja rzeczy, tak działają dyrektywy.

Zarówno $scope, jak i link mają swoje cele w Angular 1.x i są niezbędne nawet przy najnowszych wydarzeniach w społeczności. Wypędzanie ich bez ważnej przyczyny jest nadgorliwe i może prowadzić do złych rozwiązań projektowych. Brak słów "link" i "scope" w kodzie nie pomoże w ułatwieniu aplikacji do portu 2.x. Choć teraz nauczymy się teraz Angular 2 i opracujemy odpowiednie nawyki na 1.x.

0

See here lub here

  1. var parentForm = $element.inheritedData('$formController') || ....
  2. var parentForm = $element.controller('form')
Powiązane problemy