2014-04-22 4 views
14

Zwei Direktiven für dasselbe Element können nicht beide einen isolierten Bereich haben, aber können beide den gleichen Bereich verwenden, der von ihren Eltern isoliert ist? Und können beide Eigenschaften verwenden, die an den isolierten Bereich gebunden sind?Können mehrere Direktiven für ein Element einen isolierten Bereich gemeinsam nutzen?

Zum Beispiel, wenn ich zwei Richtlinien auf ein Element

<eDirective aDirective prop="parentProp"/> 

Und eine Richtlinie definiert einen isolierten Umfang mit einer gebundenen Eigenschaft

App.directive('eDirective', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     localProp: '=prop' 
    }, 
    ... 
    }; 
}); 

Ist die andere Richtlinie, dass Umfang erhalten und kann es Verwenden Sie die gebundene Eigenschaft?

App.directive('aDirective', function() { 
    return { 
    restrict: 'A', 
    link: function postLink(scope, element, attrs) { 
     scope.$watch('localProp', function(newProp, oldProp) { 
      ... 
     } 
    }, 
    ... 
    }; 
}); 

Mein erster Versuch (so ziemlich wie oben codiert) fehlgeschlagen.

+1

Was passiert, wenn Sie 'scope: {localProp: '= prop'}' für 'directive' wiederholen? –

+1

Das weist beide Direktiven an, dass jeder ihren eigenen isolierten Bereich erstellt, der nicht nur nicht das ist, was ich will, sondern auch zu einem "Mehrere Direktiven, die nach einem isolierten Bereich fragen" -Fehler führt. –

Antwort

19

Ich schlage vor, dass Sie die Kommunikation zwischen den Controllern der Direktiven über die Eigenschaft require der sekundären Direktive verwenden. Die erste Direktive (e-Direktive) enthält den isolierten Bereich, während die zweite Helper-Direktive (a-directive) einen Verweis auf die erste Direktive hat und Eigenschaften über Funktionen definiert, die in der ersten Direktive definiert sind. Eine kleine Probe wäre (see plunker):

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl"> 
    <div e-directive config="parentConfig" a-directive></div> 
    </body> 

</html> 

und die javascript:

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

app.controller('MainCtrl', function($scope) { 
    $scope.parentConfig = {}; 
}); 

app.controller('ECtrl', function ($scope) { 
    this.setProp = function(newProp){$scope.config.prop = newProp;}; 

    $scope.$watch('config', function(newProp, oldProp) { 
    console.log(oldProp, newProp); 
    }); 
}); 

app.directive('eDirective', function() { 
    return { 
    restrict: 'A', 
    scope: { 
     config: '=' 
    }, 
    controller: 'ECtrl', 
    link: function(scope, element, attrs) { 
     scope.config.prop ="abc"; 
    } 
    }; 
}); 

app.directive('aDirective', function() { 
    return { 
    restrict: 'A', 
    require: 'eDirective', 
    link: function(scope, element, attrs,ctrl) { 
     ctrl.setProp("def"); 
    } 

    }; 
}); 
+0

Ich gebe zu, ich hoffte auf eine Möglichkeit, den Umfang zu teilen, besonders wenn die Dokumentation Dinge wie "ein Element kann nur einen Bereich haben" sieht, aber wenn das nicht möglich ist, kann dies definitiv mein Problem lösen. –

1

Statt eines Isolats Umfang, die Richtlinien ein neues Kind Bereich erstellen können, die von den beiden Richtlinien gemeinsam genutzt werden. Wenn Sie parentProp in einer Richtlinie ändern müssen, injizieren und verwenden $parse:

<div ng-controller="MyCtrl"> 
    <e-directive a-directive prop="parentProp"></e-directive> 
</div> 

Javascript:

var app = angular.module('myApp', []); 
app.controller('MyCtrl', function($scope) { 
    $scope.parentProp = { prop1: 'value1' }; 
}); 
app.directive('eDirective', function($parse) { 
    return { 
    restrict: 'E', 
    scope: true, 
    template: '<div>dir template: {{eDirLocalProp}}<br>' 
      + '<a href ng-click="eDirChange()">change</a></div>', 
    link: function(scope, element, attrs) { 
     scope.eDirProp1  = 'dirPropValue'; 
     var model   = $parse(attrs.prop); 
     scope.eDirLocalProp = model(scope); 
     scope.eDirChange = function() { 
      scope.eDirLocalProp.prop1 = "new value"; 
     }; 
    } 
    }; 
}); 
app.directive('aDirective', function() { 
    return { 
    scope: true, 
    link: function postLink(scope, element, attrs) { 
     scope.$watchCollection(attrs.prop, function(newValue) { 
     console.log('aDirective', newValue); 
     }); 
    }, 
    }; 
}); 

fiddle

Wenn beide Richtlinien müssen Eigenschaften auf dem neuen Kind Bereich erstellen Verwenden Sie eine Art von Namenskonvention, um Namenskonflikte zu vermeiden. Zum Beispiel scope.eDirProp1 = ... und scope.aDirProp1 = ....

0

Yes element.isolateScope() zum Beispiel (oder siehe fiddle) mit:

HTML

<div ng-app="app" ng-controller="BaseController as baseCtrl"> 
    <input type="text" ng-model="inputA.value" directive-config="{data: 'bar'}" > 
    <input type="text" ng-model="inputB.value" directive-config="{parsers: externalParser, data: 'buzz'}" custom-input > 

    <br><br> 
    <span style="font-style: italic; font-size: 12px; color: red;">*Open Console to view output</span> 
</div> 

JS

(function(angular){ 
    "use strict"; 
    angular.module("app", []) 

    .controller("BaseController", ['$scope', function($scope){ 
    $scope.inputA = {value: "This is inputA"}; 
    $scope.inputB = {value: "This is inputB"}; 

    $scope.externalParser = function(value) { 
     console.log("...parsing value: ", value); 
    } 
    }]) 

    .directive("input", [function() { 
    return { 
     restrict: "E", 
     require: '?ngModel', 
     scope: { 
     directiveConfig: "=" 
     }, 
     link: function(scope, element, attrs, ngModelCtrl) { 
     console.log("input directive - scope: ", scope); 
     console.log("input directive - scope.directiveConfig.data: ", scope.directiveConfig.data); 
     } 
    } 
    }]) 

    .directive("customInput", [function() { 
    return { 
     restrict: "A", 
     require: '?ngModel', 
     link: function(scope, element, attrs, ngModelCtrl) { 
     console.log(""); 
     console.log("--------------------------------------------"); 
     console.log("customInput directive - scope: ", scope); 

     // Use `element.isolateScope()` 
     var parentScope = element.isolateScope(); 
     console.log("customInput directive - parentScope.directiveConfig.parsers: ", parentScope.directiveConfig.parsers); 
     console.log("customInput directive - parentScope.directiveConfig.data: ", parentScope.directiveConfig.data); 

     console.log(""); 
     console.log("--------------------------------------------"); 
     console.warn("DO NOT USE `$$childHead` as it may not target the element you are expecting; use `element.isolateScope()` instead."); 
     // DO NOT USE `$$childHead` as it may not be the element you expect 
     console.log("customInput directive - scope.$$childHead.directiveConfig.parsers: ", scope.$$childHead.directiveConfig.parsers); 
     console.log("customInput directive - scope.$$childHead.directiveConfig.data: ", scope.$$childHead.directiveConfig.data); 
     } 
    } 
    }]) 

    ; 
})(angular) 

Konsolenausgabe

//input directive - scope: n {$id: 3, $$childTail: null, $$childHead: null, $$prevSibling: null, $$nextSibling: null…} 
//input directive - scope.directiveConfig.data: bar 
//input directive - scope: n {$id: 4, $$childTail: null, $$childHead: null, $$prevSibling: n, $$nextSibling: null…} 
//input directive - scope.directiveConfig.data: buzz 

//-------------------------------------------- 
//customInput directive - scope: b {$$childTail: n, $$childHead: n, $$nextSibling: null, $$watchers: Array[4], $$listeners: Object…} 
//customInput directive - parentScope.directiveConfig.parsers: function (value) { 
//   console.log("...parsing value: ", value); 
//  } 
//customInput directive - parentScope.directiveConfig.data: buzz 

//-------------------------------------------- 
//DO NOT USE `$$childHead` as it may not target the element you are expecting; use `element.isolateScope()` instead. 
//customInput directive - scope.$$childHead.directiveConfig.parsers: undefined 
//customInput directive - scope.$$childHead.directiveConfig.data: bar 
Verwandte Themen