Ich habe eine Formaldirektive, die ein angegebenes callback
-Attribut mit einem isolierten Bereich verwendet:
scope: { callback: '&' }
Es befindet sich in einem ng-repeat
, so dass der übergebene Ausdruck die id
des Objekts als Argument für die Rückruffunktion enthält:
<directive ng-repeat = "item in stuff" callback = "callback(item.id)"/>
Wenn ich mit der Direktive fertig bin, ruft sie $scope.callback()
von ihrer Controller-Funktion auf. In den meisten Fällen ist dies in Ordnung, und ich möchte alles tun, aber manchmal möchte ich noch ein Argument aus der Variablen directive
hinzufügen.
Gibt es einen Winkelausdruck, der dies zulässt: $scope.callback(arg2)
, wodurch callback
mit arguments = [item.id, arg2]
aufgerufen wird?
Wenn nicht, wie gehe ich am besten vor?
Ich habe festgestellt, dass dies funktioniert:
<directive
ng-repeat = "item in stuff"
callback = "callback"
callback-arg="item.id"/>
Mit
scope { callback: '=', callbackArg: '=' }
und die Direktive aufrufen
$scope.callback.apply(null, [$scope.callbackArg].concat([arg2, arg3]) );
Aber ich denke nicht, dass es besonders ordentlich ist, und man muss zusätzliche Dinge in den Isolatbereich legen.
Gibt es einen besseren Weg?
Plunker Spielplatz hier (Konsole offen lassen).
Wenn du deinen Rückruf wie von @ Lex82 erwähnt deklarierst
callback = "callback(item.id, arg2)"
Sie können die Rückmeldemethode im Geltungsbereich der Direktive mit der Objektzuordnung aufrufen, und die Bindung würde ordnungsgemäß ausgeführt. Mögen
scope.callback({arg2:"some value"});
ohne $ parse zu verlangen. Siehe meine Geige (Konsolenprotokoll) http://jsfiddle.net/k7czc/2/
Update: Es gibt ein kleines Beispiel in der Dokumentation :
& oder & attr - bietet die Möglichkeit, einen Ausdruck im Kontext von .__ auszuführen. der übergeordnete Bereich. Wenn kein attr-Name angegeben wird, dann der Attributname wird als identisch mit dem lokalen Namen angenommen. Gegebene und Widget-Definition des Bereichs: { localFn: '& meinAttr'}, dann zeigt die Isolateigenschaftseigenschaft localFn auf Ein Funktionswrapper für den Ausdruck count = count + value. Häufig Es ist wünschenswert, Daten aus dem isolierten Bereich über einen Ausdruck zu übergeben und für den übergeordneten Bereich kann dies durch Übergeben einer Karte von local .__ erfolgen. Variablennamen und -werte in den Ausdrucks-Wrapper fn. Beispiel: Wenn der Ausdruck increment (Betrag) ist, können wir den Betragswert Angeben, indem Sie localFn als localFn ({Anzahl: 22}) aufrufen.
Bei den anderen Antworten ist nichts falsch, aber ich benutze die folgende Technik, wenn Sie Funktionen in einem Direktionsattribut übergeben.
Lassen Sie die Klammer weg, wenn Sie die Direktive in Ihre HTML-Datei aufnehmen:
<my-directive callback="someFunction" />
Dann "entpacken" Sie die Funktion in der Verknüpfung oder dem Controller Ihrer Direktive. Hier ist ein Beispiel:
app.directive("myDirective", function() {
return {
restrict: "E",
scope: {
callback: "&"
},
template: "<div ng-click='callback(data)'></div>", // call function this way...
link: function(scope, element, attrs) {
// unwrap the function
scope.callback = scope.callback();
scope.data = "data from somewhere";
element.bind("click",function() {
scope.$apply(function() {
callback(data); // ...or this way
});
});
}
}
}]);
Der Schritt "Entpacken" ermöglicht den Aufruf der Funktion mit einer natürlicheren Syntax. Sie stellt außerdem sicher, dass die Direktive ordnungsgemäß funktioniert, auch wenn sie in anderen Direktiven verschachtelt ist, die die Funktion übergeben können. Wenn Sie das Auspacken nicht durchgeführt haben, haben Sie ein Szenario wie dieses:
<outer-directive callback="someFunction" >
<middle-directive callback="callback" >
<inner-directive callback="callback" />
</middle-directive>
</outer-directive>
Dann würden Sie in Ihrer inneren Anweisung so etwas enden:
callback()()()(data);
Was in anderen Verschachtelungsszenarien fehlschlagen würde.
Ich habe diese Technik aus einem ausgezeichneten Artikel von Dan Wahlin in http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters angepasst.
Ich habe den Schritt zum Auspacken hinzugefügt, um das Aufrufen der Funktion natürlicher zu machen und um das Problem der Verschachtelung zu lösen, das mir in einem Projekt begegnet war.
In Direktive (myDirective
):
...
directive.scope = {
boundFunction: '&',
model: '=',
};
...
return directive;
In der Vorlage Vorlage:
<div
data-ng-repeat="item in model"
data-ng-click='boundFunction({param: item})'>
{{item.myValue}}
</div>
In der Quelle:
<my-directive
model='myData'
bound-function='myFunction(param)'>
</my-directive>
... wobei myFunction
im Controller definiert ist.
Beachten Sie, dass param
in der Direktionsvorlage sauber an param
in der Quelle gebunden ist und auf item
gesetzt ist.
Um aus der link
-Eigenschaft einer Direktive ("inside" davon) aufzurufen, verwenden Sie einen sehr ähnlichen Ansatz:
...
directive.link = function(isolatedScope) {
isolatedScope.boundFunction({param: "foo"});
};
...
return directive;
Ja, es gibt einen besseren Weg: Sie können den $ parse-Dienst in Ihrer Direktive verwenden, um einen Ausdruck im Kontext des übergeordneten Bereichs auszuwerten, während Sie bestimmte Bezeichner im Ausdruck an Werte binden, die nur in Ihrer Direktive sichtbar sind:
$parse(attributes.callback)(scope.$parent, { arg2: yourSecondArgument });
Fügen Sie diese Zeile der Link-Funktion der Direktive hinzu, in der Sie auf die Attribute der Direktive zugreifen können.
Ihr Callback-Attribut kann dann wie callback = "callback(item.id, arg2)"
festgelegt werden, da arg2 vom $ parse-Service in der Direktive an yourSecondArgument gebunden ist. Direktiven wie ng-click
ermöglichen den Zugriff auf das Klickereignis über den $event
-Bezeichner im Ausdruck, der mit genau diesem Mechanismus an die Direktive übergeben wird.
Beachten Sie, dass Sie mit dieser Lösung callback
nicht zu einem Mitglied Ihres isolierten Bereichs machen müssen.
Für mich hat folgendes gearbeitet:
in der Direktive erklären es so:
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
scope: {
myFunction: '=',
},
templateUrl: 'myDirective.html'
};
})
Verwenden Sie es in der Befehlsvorlage folgendermaßen:
<select ng-change="myFunction(selectedAmount)">
Und dann, wenn Sie die Direktive verwenden, übergeben Sie die Funktion folgendermaßen:
<data-my-directive
data-my-function="setSelectedAmount">
</data-my-directive>
Sie übergeben die Funktion durch ihre Deklaration und sie wird aus der Direktive aufgerufen und die Parameter werden aufgefüllt.