Kann eine Winkeldirektive Argumente an Funktionen in Ausdrücken übergeben, die in den Attributen der Direktive angegeben sind?
Lesezeit: 7 Minuten
Ed_
Ich habe eine Formulardirektive, die eine angegebene verwendet callback Attribut mit einem isolierten Bereich:
scope: { callback: '&' }
Es sitzt in einem ng-repeat Der Ausdruck, den ich übergebe, enthält also die id des Objekts als Argument für die Callback-Funktion:
<directive ng-repeat = "item in stuff" callback = "callback(item.id)"/>
Wenn ich mit der Direktive fertig bin, ruft sie $scope.callback() aus seiner Controller-Funktion. In den meisten Fällen ist das in Ordnung, und es ist alles, was ich tun möchte, aber manchmal möchte ich ein weiteres Argument aus dem hinzufügen directive selbst.
Gibt es einen Winkelausdruck, der dies ermöglichen würde: $scope.callback(arg2)ergebend callback mit angerufen werden arguments = [item.id, arg2]?
Wenn nicht, was ist der eleganteste Weg, dies zu tun?
Ich habe festgestellt, dass dies funktioniert:
<directive
ng-repeat = "item in stuff"
callback = "callback"
callback-arg="item.id"/>
Die Attributbezeichnung “callback=” führt in die Irre. Es ist wirklich eine Rückrufauswertung, kein Rückruf selbst.
– Dmitri Zaitsev
12. November 2015 um 4:36 Uhr
@DmitriZaitsev ist ein Callback-Winkelausdruck, der zu einer JavaScript-Funktion ausgewertet wird. Ich denke, es ist ziemlich offensichtlich, dass es sich nicht um eine JavaScript-Funktion an sich handelt. Es ist nur eine Präferenz, aber ich würde es vorziehen, nicht alle meine Attribute mit “-expression” anhängen zu müssen. Dies steht im Einklang mit der ng API zum Beispiel ng-click="someFunction()" ist ein Ausdruck, der zur Ausführung einer Funktion ausgewertet wird.
– Ed_
12. November 2015 um 13:25 Uhr
Ich habe noch nie einen Winkelausdruck namens “Rückruf” gesehen. Es ist immer eine Funktion, die Sie übergeben, um aufgerufen zu werden, woher der Name kommt. Sie verwenden in Ihrem Beispiel sogar eine Funktion namens “callback”, um die Dinge noch verwirrender zu machen.
– Dmitri Zaitsev
12. November 2015 um 15:26 Uhr
Ich bin mir nicht sicher, ob Sie verwirrt sind oder ich. In meinem Beispiel $scope.callback wird durch die eingestellt callback="someFunction" Attribut und die scope: { callback: '=' } -Eigenschaft des Direktivendefinitionsobjekts. $scope.callbackist eine später aufzurufende Funktion. Das eigentliche Attribut Wert ist offensichtlich ein String – das ist bei HTML immer so.
– Ed_
12. November 2015 um 15:31 Uhr
Sie benennen sowohl Attribut als auch Funktion gleich – “Rückruf”. Das ist das Rezept für Verwirrung. Wirklich leicht zu vermeiden.
– Dmitri Zaitsev
12. November 2015 um 15:42 Uhr
Chandermani
Wenn du deinen Callback wie von @lex82 erwähnt deklarierst like
callback = "callback(item.id, arg2)"
Sie können die Rückrufmethode im Direktivenbereich mit der Objektzuordnung aufrufen, und die Bindung würde korrekt ausgeführt. Wie
Aktualisieren: Es gibt ein kleines Beispiel dafür in der Dokumentation:
& oder &attr – bietet eine Möglichkeit, einen Ausdruck im Kontext des übergeordneten Gültigkeitsbereichs auszuführen. Wenn kein Attributname angegeben ist, wird davon ausgegangen, dass der Attributname mit dem lokalen Namen identisch ist. Gegeben und Widget-Definition des Geltungsbereichs: { localFn:’&myAttr’ }, dann isoliert die Geltungsbereichseigenschaft localFn auf einen Funktions-Wrapper für den Ausdruck count = count + value. Oft ist es wünschenswert, Daten aus dem isolierten Gültigkeitsbereich über einen Ausdruck und an den übergeordneten Gültigkeitsbereich zu übergeben. Dies kann durch Übergabe einer Zuordnung lokaler Variablennamen und -werte an den Ausdrucks-Wrapper fn erfolgen. Wenn der Ausdruck beispielsweise increment(amount) ist, können wir den Betragswert angeben, indem wir localFn als localFn({amount: 22}) aufrufen.
Sehr schön! Ist das irgendwo dokumentiert?
– ach
17. Oktober 2014 um 20:09 Uhr
Ich denke nicht, dass dies eine gute Lösung ist, da Sie in der Direktivendefinition manchmal nicht wissen, welcher Parameter übergeben werden muss.
– OMGPOP
2. Juli 2015 um 6:58 Uhr
Dies ist eine gute Lösung und vielen Dank dafür, aber ich glaube, die Antwort muss ein wenig überarbeitet werden. Wer ist lex82 und was hat er erwähnt?
– Wturm
17. Dezember 2016 um 21:29 Uhr
Interessanter Ansatz. Was passiert jedoch, wenn Sie zulassen möchten, dass eine Funktion mit einem beliebigen Parameter (oder mehreren) übergeben wird? Sie wissen nichts über die Funktion oder ihre Parameter und müssen sie bei einem Ereignis innerhalb der Direktive ausführen. Wie geht man vor? Zum Beispiel könnten Sie bei einer Direktive onchangefunc=’myCtrlFunc(dynamicVariableHere)’ haben.
– Zugoase
22. Januar 2018 um 8:08 Uhr
An den anderen Antworten ist nichts auszusetzen, aber ich verwende die folgende Technik, wenn ich Funktionen in einem Direktivenattribut übergebe.
Lassen Sie die Klammer weg, wenn Sie die Direktive in Ihren HTML-Code einfügen:
<my-directive callback="someFunction" />
Dann “entpacken” Sie die Funktion im Link oder 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 “Unwrapping” ermöglicht es, die Funktion mit einer natürlicheren Syntax aufzurufen. Es stellt auch sicher, dass die Direktive ordnungsgemäß funktioniert, selbst wenn sie in anderen Direktiven verschachtelt ist, die die Funktion möglicherweise übergeben. Wenn Sie das Auspacken nicht durchgeführt haben, dann haben Sie ein Szenario wie dieses:
Ich habe den Unwrapping-Schritt hinzugefügt, um das Aufrufen der Funktion natürlicher zu gestalten und das Verschachtelungsproblem zu lösen, auf das ich in einem Projekt gestoßen bin.
Ein netter Ansatz, aber ich bin nicht in der Lage, den zu verwenden this Zeiger innerhalb der Callback-Methode, da sie den Gültigkeitsbereich der Direktive verwendet. Ich verwende Typescript und mein Callback sieht so aus: public validateFirstName(firstName: string, fieldName: string): ng.IPromise<boolean> { var deferred = this.mQService.defer<boolean>(); ... .then(() => deferred.resolve(true)) .catch((msg) => { deferred.reject(false); }); return deferred.promise; }
– nee
24. Juni 2015 um 9:05 Uhr
Hinweis: Wenn Sie verschachtelte Direktiven haben und den Callback nach oben weitergeben möchten, müssen Sie jede Direktive auspacken, nicht nur die, die den Callback auslöst.
Während Sie In source: bound-function=’myFunction(obj1.param, obj2.param)’> haben, wie gehen Sie dann vor?
– Ankit Pandey
13. Januar 2020 um 8:25 Uhr
Ja, es gibt einen besseren Weg: Sie können die verwenden $parse-Dienst in Ihrer Direktive, um einen Ausdruck im Kontext des übergeordneten Bereichs auszuwerten, während bestimmte Bezeichner im Ausdruck an Werte gebunden werden, die nur innerhalb Ihrer Direktive sichtbar sind:
Fügen Sie diese Zeile zur Link-Funktion der Direktive hinzu, wo Sie auf die Attribute der Direktive zugreifen können.
Ihr Callback-Attribut kann dann wie folgt gesetzt werden callback = "callback(item.id, arg2)" weil arg2 durch den $parse-Dienst innerhalb der Direktive an yourSecondArgument gebunden ist. Direktiven wie ng-click ermöglichen Ihnen den Zugriff auf das Click-Ereignis über die $event Bezeichner innerhalb des Ausdrucks, der an die Direktive übergeben wird, indem genau dieser Mechanismus verwendet wird.
Beachten Sie, dass Sie dies nicht tun müssen callback ein Mitglied Ihres isolierten Geltungsbereichs mit dieser Lösung.
Die Attributbezeichnung “callback=” führt in die Irre. Es ist wirklich eine Rückrufauswertung, kein Rückruf selbst.
– Dmitri Zaitsev
12. November 2015 um 4:36 Uhr
@DmitriZaitsev ist ein Callback-Winkelausdruck, der zu einer JavaScript-Funktion ausgewertet wird. Ich denke, es ist ziemlich offensichtlich, dass es sich nicht um eine JavaScript-Funktion an sich handelt. Es ist nur eine Präferenz, aber ich würde es vorziehen, nicht alle meine Attribute mit “-expression” anhängen zu müssen. Dies steht im Einklang mit der
ng
API zum Beispielng-click="someFunction()"
ist ein Ausdruck, der zur Ausführung einer Funktion ausgewertet wird.– Ed_
12. November 2015 um 13:25 Uhr
Ich habe noch nie einen Winkelausdruck namens “Rückruf” gesehen. Es ist immer eine Funktion, die Sie übergeben, um aufgerufen zu werden, woher der Name kommt. Sie verwenden in Ihrem Beispiel sogar eine Funktion namens “callback”, um die Dinge noch verwirrender zu machen.
– Dmitri Zaitsev
12. November 2015 um 15:26 Uhr
Ich bin mir nicht sicher, ob Sie verwirrt sind oder ich. In meinem Beispiel
$scope.callback
wird durch die eingestelltcallback="someFunction"
Attribut und diescope: { callback: '=' }
-Eigenschaft des Direktivendefinitionsobjekts.$scope.callback
ist eine später aufzurufende Funktion. Das eigentliche Attribut Wert ist offensichtlich ein String – das ist bei HTML immer so.– Ed_
12. November 2015 um 15:31 Uhr
Sie benennen sowohl Attribut als auch Funktion gleich – “Rückruf”. Das ist das Rezept für Verwirrung. Wirklich leicht zu vermeiden.
– Dmitri Zaitsev
12. November 2015 um 15:42 Uhr