Also habe ich diese Direktive sagen, mySave
, es ist so ziemlich alles
app.directive('mySave', function($http) {
return function(scope, element, attrs) {
element.bind("click", function() {
$http.post('/save', scope.data).success(returnedData) {
// callback defined on my utils service here
// user defined callback here, from my-save-callback perhaps?
}
});
}
});
das Element selbst sieht so aus
<button my-save my-save-callback="callbackFunctionInController()">save</button>
callbackFunctionInController ist vorerst nur
$scope.callbackFunctionInController = function() {
alert("callback");
}
wenn ich console.log()
attrs.mySaveCallback
in my-save-Direktive besitze, gibt es mir nur eine Zeichenfolge callbackFunctionInController()
. Ich las irgendwo , dass ich dies $ parse und es wäre gut, also versuchte ich $parse(attrs.mySaveCallback)
, was mir etwas Funktion gab Kaum der, nach dem ich gesucht hatte, gab mich zurück
function (a,b){return m(a,b)}
Was mache ich falsch? Ist dieser Ansatz von Anfang an fehlerhaft?
Was also der beste Weg zu sein scheint, ist die Verwendung des isolierten Bereichs, wie von ProLoser vorgeschlagen
app.directive('mySave', function($http) {
return {
scope: {
callback: '&mySaveCallback'
}
link: function(scope, element, attrs) {
element.on("click", function() {
$http.post('/save', scope.$parent.data).success(returnedData) {
// callback defined on my utils service here
scope.callback(); // fires alert
}
});
}
}
});
Um Parameter zurück an den Controller zu übergeben, tun Sie dies
[11:28] <revolunet> you have to send named parameters
[11:28] <revolunet> eg my-attr="callback(a, b)"
[11:29] <revolunet> in the directive: scope.callback({a:xxx, b:yyy})
Es gibt viele Möglichkeiten, was Sie tun. Das ERSTE, was Sie wissen sollten, ist, dass die $http.post()
aufgerufen wird, sobald dieses DOM-Element von der Template-Engine ausgegeben wird. Wenn Sie es in eine Wiederholung einfügen, wird der Anruf für jeden neuen Eintrag im Repeater erledigt. Ich vermute, dies ist definitiv nicht das, was Sie wollen. Und wenn ist , dann entwerfen Sie wirklich nicht die richtigen Dinge, da die Existenz von DOM alleine keine Anfragen an das Backend diktieren sollte.
Wie auch immer, direkt auf deine Frage antworten; Wenn Sie die zwar beschissenen Dokumente in $ parse lesen, erhalten Sie einen Bewertungsausdruck. Wenn Sie diese Funktion ausführen, indem Sie den Gültigkeitsbereich für die Auswertung übergeben, wird der aktuelle Status dieses Ausdrucks für den von Ihnen übergebenen Gültigkeitsbereich zurückgegeben. Dies bedeutet, dass Ihre Funktion ausgeführt wird.
var expression = $parse(attrs.mySave);
results = expression($scope); // call on demand when needed
expression.assign($scope, 'newValu'); // the major reason to leverage $parse, setting vals
Ja, es ist anfangs etwas verwirrend, aber Sie müssen verstehen, dass sich ein $ -Bereich in asynchronen Apps ständig ändert. $parse
ist nützlicher für einen Verweis auf ein Modell, dem Sie einen Wert zuweisen und nicht nur lesen möchten.
Natürlich möchten Sie vielleicht wissen, wie Sie einen Isolat-Bereich erstellen oder wie Sie einen Ausdruck $eval()
erstellen.
$scope.$eval(attrs.mySave);
Sie können . $ Eval verwenden, um eine Anweisung im angegebenen Bereich auszuführen
app.directive('mySave', function($http) {
return function(scope, element, attrs) {
$http.post('/save', scope.data).success(returnedData) {
// callback defined on my utils service here
// user defined callback here, from my-save-callback perhaps?
scope.$eval(attrs.mySaveCallback)
}
}
});
TD: Demo
Wenn Sie Daten für eine Direktive und einen Controller freigeben möchten, können Sie die bidirektionale Bindung verwenden
app.controller('AppController', function ($scope) {
$scope.callbackFunctionInController = function() {
console.log('do something')
};
$scope.$watch('somedata', function(data) {
console.log('controller', data);
}, true);
});
app.directive('mySave', function($http, $parse) {
return {
scope: {
data: '=mySaveData',
callback: '&mySaveCallback' //the callback
},
link: function(scope, element, attrs) {
$http.get('data.json').success(function(data) {
console.log('data', data);
scope.data = data;
scope.callback(); //calling callback, this may not be required
});
}
};
});
Demo: Fiddle
scope: {
callback: '&mySaveCallback'
}
Das explizite Festlegen des Bereichs könnte eine gute Lösung sein, aber wenn Sie andere Teile des ursprünglichen Bereichs erreichen möchten, können Sie dies nicht, da Sie ihn gerade überschrieben haben. Aus irgendeinem Grund musste ich auch andere Bereiche des Gültigkeitsbereichs erreichen, also verwendete ich dieselbe Implementierung wie ng-click do.
Die Verwendung meiner Direktive in HTML:
<div my-data-table my-source="dataSource" refresh="refresh(data)">
Innerhalb der Direktive (ohne den Geltungsbereich explizit festzulegen):
var refreshHandler = $parse(attrs.refresh);
scope.$apply(function () {
refreshHandler( {data : conditions}, scope, { $event: event });
});
Hiermit kann ich die Funktion im Controller aufrufen und Parameter übergeben.
In der Steuerung:
$scope.refresh= function(data){
console.log(data);
}
Und es druckt die Bedingungen richtig aus.
app.directive('mySave', function($http, $parse) {
return {
scope: {
data: '=mySaveData',
callback: '&' //the callback
},
link: function(scope, element, attrs) {
$http.get('data.json').success(function(data) {
console.log('data', data);
if (scope.callback()) scope.callback().apply(data);
});
}
};
});
Sie sollten ng-click
verwenden, anstatt eine eigene Direktive zu erstellen.
Das hat bei mir funktioniert
Im View-Skript
<tag mycallbackattrib="scopemethod">
In der Direktive
$scope[attrs.mycallbackattrib](params....);
Es wird korrekt aufgerufen und Parameter werden übergeben, aber es ist vielleicht nicht der beste "Winkelweg", um zu arbeiten.