2013-05-31 6 views
29

Ich möchte auf den Geltungsbereich einer übergeordneten Richtlinie zugreifen, aber ich kann nicht die richtige Kombination von Einstellungen erhalten. Ist das möglich und ist es der richtige Ansatz?Access Parent Scope in abgeleiteter Direktive

Ich möchte wirklich vermeiden, so etwas wie SOME_CONST setzen (was mich DOM Flow aktualisiert durch die Kontrolle machen würde helfen) in MyCtrl

<div ng-controller="MyCtrl"> 
    <parent> 
     <child></child> 
    </parent> 
</div> 

var myApp = angular.module('myApp',[]); 

function MyCtrl($scope) { 
    $scope.obj = {prop:'foo'}; 
} 

myApp.directive('parent', function() { 
    return { 
     scope: true, 
     transclude: true, 
     restrict: 'EA', 
     template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>', 
     link: function(scope, elem, attrs) { 
      scope.SOME_CONST = 'someConst'; 
     } 
    } 
}); 

myApp.directive('child', function() { 
    return { 
     restrict: 'EA', 
     template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t. I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function? is this even a good idea? {{SOME_CONST}}. I really don\'t want to put everything inside the MyCtrl', 
    } 
}); 

finden Sie in diesem fiddle

Dank

Antwort

42

Mit transclude: true und scope: true, die parent Richtlinie schafft zwei neue Bereiche: enter image description here

Scope 004 ist ein Ergebnis der scope: true und Umfang 005 ist ein Ergebnis der transclude: true. Da die child Direktive keinen neuen Bereich erstellt, verwendet sie den durchbrochenen Bereich 005. Wie Sie aus dem Diagramm sehen können, gibt es keinen Pfad vom Bereich 005 zum Bereich 004 (außer über die private Eigenschaft $$ prevShibling, die in die entgegengesetzte Richtung von $$ nextSibling - aber nicht mit denen verwenden)

@ joakimbl-Lösung am besten ist wohl hier, obwohl ich denke, es ist häufiger eine API für die übergeordnete Richtlinie des Controllers, anstatt definierenden Eigenschaften auf this zu definieren:

.
controller: function($scope) { 
    $scope.SOME_CONST = 'someConst'; 
    this.getConst = function() { 
     return $scope.SOME_CONST; 
    } 
} 

Dann in der child Richtlinie:

link:function(scope,element,attrs,parentCtrl){ 
    scope.SOME_CONST = parentCtrl.getConst(); 
}, 

So funktionieren die Anweisungen tabs und pane auf Angulars Homepage (Beispiel "Create Components").

+0

@ Mark Rajcok - Große Antwort Mark, Sie scheinen einer der wenigen Leute auf dieser Seite zu sein, die Angular wirklich vollständig verstehen. Ich habe eine ähnliche Frage, aber unter diesem Link: [link] (http://stackoverflow.com/questions/23437113/get-property-value-from-parent-directive-within-child-directive). Mein Problem ist, dass zu dem Zeitpunkt, zu dem die Link-Methode für die Child-Direktive ausgeführt wird, die Vorlage der Child-Direktive bereits gerendert wurde. Das bedeutet, dass ich die Elterneigenschaft innerhalb des untergeordneten Elements nicht verwenden kann, um Bereichsvariablen vor dem Rendern festzulegen. –

+0

Dies ist großartig, aber es scheint, dass dieser Wert kopiert wird, anstatt gebunden (dh Zwei-Wege-Datenbindung) –

+0

Zustimmen, das ist nicht bidirektionale Daten gebunden. Um die ursprüngliche Frage zu beantworten, muss der Kind-Controller einfach auf den Bereich. $ Parent zugreifen und er hat die Vorteile der Vererbung und der bidirektionalen Datenbindung. – CarbonDry

9

Normalerweise wird die Art und Weise Sie greifen auf eine übergeordnete Bereichsvariable in einer Direktive durch bidirektionale Bindung zu (scope:{model:'=model'} - siehe the angular guide on directives) in der Direktivenkonfiguration), aber da Sie die Transclusion verwenden, ist dies nicht so geradlinig. Wenn das Kind Richtlinie wird immer ein Kind der Eltern-Richtlinie sein können Sie aber es konfigurieren, dass die Eltern zu verlangen, und dann den Zugriff auf die übergeordnete Steuerung in der Kind-Link-Funktion erhalten:

myApp.directive('parent', function() { 
    return { 
    scope: true, 
    transclude: true, 
    restrict: 'EA', 
    template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>', 
    controller: function($scope) { 
     $scope.SOME_CONST = 'someConst'; 
     this.SOME_CONST = $scope.SOME_CONST; 
    } 
    } 
}); 

myApp.directive('child', function() { 
    return { 
    restrict: 'EA', 
    require:'^parent', 
    scope:true, 
    link:function(scope,element,attrs,parentCtrl){ 
     scope.SOME_CONST = parentCtrl.SOME_CONST; 
    }, 
    template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t. I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function? is this even a good idea? {{SOME_CONST}}. I really don\'t want to put everything inside the MyCtrl', 
    } 
}); 

dieses Update Siehe: http://jsfiddle.net/uN2uv/

0

Es gibt eine Transcclude Fn in den Argumenten der Verbindung Fn nach dem Controller.

myApp.directive('parent', function() { 
    return { 
    scope: true, 
    transclude: true, 
    restrict: 'EA', 
    template: '<div><h1>I'm a parent header.</h1></div>', 
    link: function (scope, el, attrs, ctrl, transclude) { 

     transclude(scope, function (clone, scope) { 
      element.append(clone); // <-- will transclude it's own scope 
     }); 

    }, 
    controller: function($scope) { 
     $scope.parent = { 
      binding: 'I\'m a parent binding' 
     }; 
    } 
    } 
}); 

myApp.directive('child', function() { 
    return { 
    restrict: 'EA', 
    require:'^parent', 
    scope:true, 
    link:function(scope,element,attrs,parentCtrl){ 

    }, 
    template: '<div>{{parent.binding}}</div>' // <-- has access to parent's scope 
    } 
}); 
6

Ich hatte gerade das gleiche Problem und schließlich löste es mit dem Winkel Handbuch;)

Kurz gesagt: Sie Controller in Ihre Mutter Richtlinie und verlangen, dass Controller verwenden müssen in Ihre Kind Direktive. Auf diese Weise können Sie Ihre übergeordneten Eigenschaften abrufen.

Siehe https://docs.angularjs.org/guide/directive Kapitel: Erstellen von Richtlinien, die

Kommunizieren

ich Ihre Geige geändert, um einen Controller zu verwenden, jetzt können Sie Ihre konstanten Zugang: https://jsfiddle.net/bbrqdmt3/1/

var myApp = angular.module('myApp',[]); 

function MyCtrl($scope) { 
    $scope.obj = {prop:'foo'}; 
} 

myApp.directive('parent', function() { 
    return { 
     scope: true, 
     transclude: true, 
     restrict: 'EA', 
     template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>', 
     controller: function($scope) { 
      this.getConst= function() { 
       return 'someConst'; 
      }       
     }, 
    } 
}); 

myApp.directive('child', function() { 
    return { 
     restrict: 'EA', 
     require : '^parent', 
     link: function(scope, element, attrs, ctrl) { 
      scope.value= ctrl.getConst(); 
     }, 
     template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t. I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function? is this even a good idea? {{value}}. I really don\'t want to put everything inside the MyCtrl', 
    } 
}); 
Verwandte Themen