Reputation: 1145
I have written an application in AngularJS and one of the requirements I am working on is to drag elements from left and drop that element to right container. All the elements from left does get dropped over to right container one by done fine. But when I click on x icon to move them back to left container, I can only move items that are in blue and item ("Manual Intervention") in green color, I cannot move back to left container. I have attached ng-click
to a link
to trigger a function to detach all items that are cloned and move items that are not cloned. I think this part $rootScope.removeDraggedItem
of the code in my js doesnt bind correctly when it is moved from left to right for "Manual Intervention" element and its unable to execute the function.
Here is the link to my JSFiddle.
Here is my code:
HTML
<div class="panel panel-default" ng-app="app" ng-controller="appCtrl">
<div class="panel-heading">Components configuration:</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-3">
<div class="jumbotron" style="min-height: 300px;">
<div class="container">
<div class="">
<ul class="list-group" id="dropleft">
<li class="ui-state-default drag-n-drop" drag-option="dropleft" ng-repeat="component in components">
<span class="label label-primary">{{component.name}}
<a href="#" ng-click="$root.removeDraggedItem($event)"><i style="color: white" class="fa fa-times hidden" aria-hidden="true"></i></a>
</span>
</li>
<li class="ui-state-default drag-n-drop-clone" drag-option="clone" detach-element>
<span class="label label-success">Manual Intervention
<a href="#" ng-click="$root.removeDraggedItem($event)"><i style="color: white" class="fa fa-times hidden" aria-hidden="true"></i></a>
</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="col-lg-9">
<div class="jumbotron sortable" id="dropright" style="min-height: 300px;">
</div>
</div>
</div>
</div>
</div>
JS code:
var app = angular.module('app', []);
app.controller('appCtrl', function($scope, $rootScope) {
$scope.title = "Test";
$rootScope.removeDraggedItem = function($event) {
var element = $(event.target).closest("li");
console.log(element.attr("drag-option"));
if (element.attr("drag-option") === "clone") {
element.detach();
} else {
// Move to its original place
console.log("No clone detected! Moving element to its original place...");
var attrVal = element.attr("drag-option");
$(element).find("i").addClass("hidden");
$(element).detach().appendTo("#" + attrVal);
}
};
$scope.components = [{
"name": "Component App1"
}, {
"name": "Component App2"
}, {
"name": "Component App3"
}, {
"name": "Component SQL1"
}, {
"name": "Component SQL2"
}];
});
app.directive('dragNDrop', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
element.draggable({
connectToSortable: "#dropright",
revert: function(event, ui) {
// on older version of jQuery use "draggable"
// $(this).data("draggable")
// on 2.x versions of jQuery use "ui-draggable"
// $(this).data("ui-draggable")
$(this).data("uiDraggable").originalPosition = {
top: 0,
left: 0
};
// return boolean
return !event;
// that evaluate like this:
// return event !== false ? false : true;
}
});
$('#dropright').droppable({
drop: function(event, ui) {
$(this).find("li").find("i").removeClass("hidden");
}
});
}
}
})
.directive('detachElement', function() {
return {
restrict: 'AC',
link: function($scope, element, attrs) {
element.find("a").bind('click', function() {
console.log("working now???");
});
}
}
})
.directive('dragNDropClone', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
element.draggable({
connectToSortable: "#dropright",
helper: 'clone',
invert: false
});
}
}
})
.directive('sortable', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
element.sortable({
cursor: 'move',
revert: true
});
}
}
});
CSS:
ul,
li {
list-style-type: none;
}
/*
Release Dashboard
*/
.dashboard-header {
margin-top: 31px;
}
.release-action-btn {
border-color: #fff;
}
.status-color-red {
background-color: #d9534f;
color: white;
}
.status-color-success {
background-color: #5cb85c;
color: white;
}
.status-color-new {
background-color: #999999;
color: white;
}
.status-color-inprogress {
background-color: #337ab7;
color: white;
}
.panel-default > .panel-heading, .table-header, .navbar-inverse {
background-color: #164c9c !important;
color: white;
}
UPDATE:
Fixed the issue by adding on click event to droppable. See below code.
$('#dropright').droppable({
drop: function (event, ui) {
$(this).find("li").find("i").removeClass("hidden");
if ($(this).find("li").attr("drag-option") === "clone")
{
console.log($(this).find("li").find("a"));
$(this).find("li").find("a").on('click', function (evt) {
evt.preventDefault();
$(this).closest("li").remove();
})
}
}
});
Upvotes: 1
Views: 783
Reputation: 30893
Forked you fiddle. I found one issue in this code:
$rootScope.removeDraggedItem = function($event) {
var element = $(event.target).closest("li");
console.log(element.attr("drag-option"));
if (element.attr("drag-option") === "clone") {
element.detach();
} else {
// Move to its original place
console.log("No clone detected! Moving element to its original place...");
var attrVal = element.attr("drag-option");
$(element).find("i").addClass("hidden");
$(element).detach().appendTo("#" + attrVal);
}
};
You define the function attribute as $event
and then call on event
within the function. I used the following:
https://jsfiddle.net/Twisty/hd234vq8/
JavaScript
var app = angular.module('app', []);
app.controller('appCtrl', function($scope, $rootScope) {
$scope.title = "Test";
$rootScope.removeDraggedItem = function(event) {
var element = $(event.target).closest("li");
console.log(element.attr("drag-option"));
if (element.attr("drag-option") === "clone") {
element.detach();
} else {
// Move to its original place
console.log("No clone detected! Moving element to its original place...");
var attrVal = $("#" + element.attr("drag-option"));
element.find("i").addClass("hidden");
var attrPos = attrVal.position();
element.css("position", "absolute");
element.animate({
//top: (attrPos.top + attrVal.find("li:last").height()),
top: "-=250",
left: attrPos.left
}, function() {
element.detach().appendTo(attrVal);
element.attr("style", "").css("position", "relative");
});
}
};
$scope.components = [{
"name": "Component App1"
}, {
"name": "Component App2"
}, {
"name": "Component App3"
}, {
"name": "Component SQL1"
}, {
"name": "Component SQL2"
}];
});
app.directive('dragNDrop', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
element.draggable({
connectToSortable: "#dropright",
revert: function(event, ui) {
// on older version of jQuery use "draggable"
// $(this).data("draggable")
// on 2.x versions of jQuery use "ui-draggable"
// $(this).data("ui-draggable")
$(this).data("uiDraggable").originalPosition = {
top: 0,
left: 0
};
// return boolean
return !event;
// that evaluate like this:
// return event !== false ? false : true;
}
});
$('#dropright').droppable({
drop: function(event, ui) {
$(this).find("li").find("i").removeClass("hidden");
}
});
}
}
})
.directive('detachElement', function() {
return {
restrict: 'AC',
link: function($scope, element, attrs) {
element.find("a").bind('click', function() {
console.log("working now???");
});
}
}
})
.directive('dragNDropClone', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
element.draggable({
connectToSortable: "#dropright",
helper: 'clone',
invert: false
});
}
}
})
.directive('sortable', function() {
return {
restrict: 'C',
link: function(scope, element, attrs) {
element.sortable({
cursor: 'move',
revert: true
});
}
}
});
If a user drags an item to another list, I like to animate the return. You will see this in the code above.
Update
Per your update, I suggest the following in droppable:
$('#dropright').droppable({
drop: function(event, ui) {
var item = $(this).find("li");
item.find("i").removeClass("hidden");
if (item.attr("drag-option") === "clone") {
console.log(item.find("a"));
item.find("a").click(function(evt) {
evt.preventDefault();
item.remove();
});
}
}
});
This will be a good option to ensure that there is a callback bound to the event. You can use .click()
here since you're assigning it directly. If you were assigning it before the element existed, you could use .on()
. Ether way is still going to work.
One other thing I noticed, is that within #dropright
, there is no <ul>
element. This is not an issue, yet it does come across as odd. Felt it was worth mentioning.
Upvotes: 1