So I keep reading that jQuery manipulation from within a Controller is bad practice, but I'm not clear on why, or how to correct.
Below is code from a Youtube tutorial which even the video creator comments is a bad idea, but doesn't explain why and continues to use the bad behavior anyway.
From https://www.youtube.com/watch?v=ilCH2Euobz0#t=553s :
$scope.delete = function() {
var id = this.todo.Id;
Todo.delete({id: id}, function() {
$('todo_' + id).fadeOut();
});
};
SOLUTION:
Based on Langdon's answer below, I've arrived at the following working code for my own work, which derives slightly from the example code above:
var ProjectListCtrl = function ($scope, Project) {
$scope.projects = Project.query();
$scope.delete = function() {
var thisElem = this;
var thisProject = thisElem.project;
var id = thisProject.id;
Project.delete({id: id}, function() {
var idx = $scope.projects.indexOf(thisProject);
if (idx !== -1) {
thisElem.destroy('removeItem('+idx+')');
}
});
}
$scope.removeItem = function(idx) {
$scope.projects.splice(idx, 1);
}
}
app.directive('fadeOnDestroy', function() {
return function(scope, elem) {
scope.destroy = function(funcComplete) {
elem.fadeOut({
complete: function() {
scope.$apply(funcComplete)
}
});
}
}
});
This differs from Langdon's answer in a few ways. I wanted to avoid adding a parameter to the ngClick
callback, so I'm storing it in thisProject
. Also, the example and my code needs to call destroy
from within a $http
success callback so instead of this
which is no longer relevant, I'm storing the clicked element in thisElem
.
UPDATE 2:
Updated my solution further to reflect that funcComplete was not actually modifying the original $scope.