In my last post, I implemented drag and drop with clone using JQuery. Now, it was time to integrate it into an application I am building, and thus had to "angularize" the implementation.
There are many drag and drop implementations on Angular out there.
The Angular docs include a simple example on directives that add/handle event listeners to implement dragging. Unfortunately, it is pretty rudimentary and it does not support cloning the draggable.
This one by Ben Parker builds from scratch on top of angular without using JQuery UI. It is an interesting approach but it is more pedagogical than anything else since it misses out on all the goodies provided by JQuery UI and its plugins.
This one by Amit Gharat combines the power of JQuery UI and Angular declarative clarity. However, it was too constraining for my needs. To use it, the drag source and drop target both have to have an underlying model and all manipulation happens to the model. If you needed to further manipulate to the dropped object, you would have to write some custom handlers. Besides, I found some oddities when trying it out, like behaving in a strange way if you did not add certain attributes.
Other implementations such as ngDraggable had similar issues.
After this tour, I decided to roll my own. I did not need something generic so I wrote a narrow solution that fit my needs. The code is basically the same that I posted in my last post but wrapped in directives and controllers.
angular.module('coach.field', [])
.directive("cloneDraggable", function() {
return {
link: function(scope, element, attrs, controller) {
element.draggable({ helper:'clone',
revert: 'invalid',
cursor: "crosshair"});
}
}
})
.controller("soccerFieldCtrl", function(tacticsService, $scope) {
$scope.idCounter = 0;
this.nextId = function() {
return $scope.idCounter++;
};
})
.directive("soccerField", function(tacticsService) {
return {
templateUrl: "field/field.html",
controller: "soccerFieldCtrl",
link: function(scope, element, attrs, controller) {
element.droppable({
drop: function(ev, ui) {
if (! ui.helper.hasClass("toolbar-gadget"))
return;
var dropped=$(ui.draggable).clone();
var newId = "player" + controller.nextId();
dropped.attr("id", newId);
var pos=$(ui.helper).offset();
var newX = pos.left- element.offset().left;
var newY = pos.top - element.offset().top;
dropped.css({"left":newX,"top":newY, "z-index": 100});
dropped.removeClass("toolbar-gadget");
dropped.addClass("player");
$(this).append(dropped);
dropped.draggable({ cursor: "crosshair",
containment: 'parent'});
}
});
}
}
});
There are many drag and drop implementations on Angular out there.
The Angular docs include a simple example on directives that add/handle event listeners to implement dragging. Unfortunately, it is pretty rudimentary and it does not support cloning the draggable.
This one by Ben Parker builds from scratch on top of angular without using JQuery UI. It is an interesting approach but it is more pedagogical than anything else since it misses out on all the goodies provided by JQuery UI and its plugins.
This one by Amit Gharat combines the power of JQuery UI and Angular declarative clarity. However, it was too constraining for my needs. To use it, the drag source and drop target both have to have an underlying model and all manipulation happens to the model. If you needed to further manipulate to the dropped object, you would have to write some custom handlers. Besides, I found some oddities when trying it out, like behaving in a strange way if you did not add certain attributes.
Other implementations such as ngDraggable had similar issues.
After this tour, I decided to roll my own. I did not need something generic so I wrote a narrow solution that fit my needs. The code is basically the same that I posted in my last post but wrapped in directives and controllers.
angular.module('coach.field', [])
.directive("cloneDraggable", function() {
return {
link: function(scope, element, attrs, controller) {
element.draggable({ helper:'clone',
revert: 'invalid',
cursor: "crosshair"});
}
}
})
.controller("soccerFieldCtrl", function(tacticsService, $scope) {
$scope.idCounter = 0;
this.nextId = function() {
return $scope.idCounter++;
};
})
.directive("soccerField", function(tacticsService) {
return {
templateUrl: "field/field.html",
controller: "soccerFieldCtrl",
link: function(scope, element, attrs, controller) {
element.droppable({
drop: function(ev, ui) {
if (! ui.helper.hasClass("toolbar-gadget"))
return;
var dropped=$(ui.draggable).clone();
var newId = "player" + controller.nextId();
dropped.attr("id", newId);
var pos=$(ui.helper).offset();
var newX = pos.left- element.offset().left;
var newY = pos.top - element.offset().top;
dropped.css({"left":newX,"top":newY, "z-index": 100});
dropped.removeClass("toolbar-gadget");
dropped.addClass("player");
$(this).append(dropped);
dropped.draggable({ cursor: "crosshair",
containment: 'parent'});
}
});
}
}
});
No comments:
Post a Comment