J'ai donc cette directive appelée par exemple, mySave
, c'est à peu près tout cela
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?
}
});
}
});
l'élément lui-même ressemble à ceci
<button my-save my-save-callback="callbackFunctionInController()">save</button>
callbackFunctionInController est pour l'instant juste
$scope.callbackFunctionInController = function() {
alert("callback");
}
quand je console.log()
attrs.mySaveCallback
dans la directive my-save, il me donne simplement une chaîne callbackFunctionInController()
, je lis quelque part que je devrais $ analyser ce script et que ça irait, alors j'ai essayé de $parse(attrs.mySaveCallback)
qui m'a donné une fonction, mais à peine celle que je cherchais, elle me rendit
function (a,b){return m(a,b)}
Qu'est-ce que je fais mal? Cette approche est-elle défectueuse depuis le début?
Donc, ce qui semble être la meilleure solution consiste à utiliser la portée isolée suggérée par ProLoser.
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
}
});
}
}
});
Pour renvoyer les paramètres au contrôleur, faites ceci
[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})
Il y a beaucoup de façons de faire ce que vous faites. La PREMIÈRE chose que vous devriez savoir est que la $http.post()
sera appelée dès que cet élément DOM sera rendu par le moteur de gabarit, et c'est tout. Si vous le mettez dans une répétition, l'appel sera effectué pour chaque nouvel élément du répéteur. Je suppose donc que ce n'est certainement pas ce que vous voulez. Et s’il est alors vous ne concevez pas vraiment les choses correctement car l’existence de DOM seul ne devrait pas dicter les requêtes au backend.
Quoi qu'il en soit, répondez directement à votre question. Si vous lisez les docs, bien que douteux, sur $ parse, il vous renvoie une expression d'évaluation. Lorsque vous exécutez cette fonction en transmettant la portée à évaluer, l'état actuel de cette expression sur la portée que vous avez transmise est renvoyé. Cela signifie que votre fonction sera exécutée.
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
Oui, c'est un peu déroutant au début, mais vous devez comprendre qu'un $ scope change constamment dans les applications asynchrones et tout dépend de QUAND vous voulez que la valeur soit déterminée, pas seulement comment. $parse
est plus utile pour faire référence à un modèle auquel vous voulez pouvoir attribuer une valeur, pas seulement lire.
Bien sûr, vous voudrez peut-être vous renseigner sur la création d'une étendue d'isolement ou sur la manière de $eval()
une expression.
$scope.$eval(attrs.mySave);
Vous pouvez utiliser . $ Eval pour exécuter une instruction dans la portée donnée
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: Démo
Si vous souhaitez partager des données entre une directive et un contrôleur, vous pouvez utiliser la liaison bidirectionnelle.
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
});
}
};
});
Démo: Fiddle
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);
});
}
};
});
Vous devriez utiliser ng-click
au lieu de créer votre propre directive.
Cela a fonctionné pour moi
Dans le script de vue
<tag mycallbackattrib="scopemethod">
À l'intérieur de la directive
$scope[attrs.mycallbackattrib](params....);
Il est correctement appelé et les paramètres sont passés, mais ce n’est peut-être pas la meilleure "manière angulaire" de travailler.