9

I'm trying to implement drag and drop system in angularjs.

I want dragged object to be cloned on drag start. However I have no idea how to clone an element along with it's scope and linked controller in angularjs?

Any suggestions?

4
  • 2
    There's angular.copy for deep copying, but I'm not sure what you mean by "...along with it's scope and linked controller...". Commented Mar 15, 2013 at 17:27
  • 2
    The "destination" parameter in angular.clone ethod is defined as: {(Object|Array)=} but i'm trying to clone html element with, listeners, scope, controller and everything. I want to create the clone of dragged html element (a directive). Commented Mar 16, 2013 at 18:06
  • 1
    I see. Maybe you'll want to edit your question and replace 'object' with 'element'. Commented Mar 16, 2013 at 18:09
  • ohhh, right. thx for noticing it. Commented Mar 17, 2013 at 10:59

2 Answers 2

10

Cloning DOM elements as it is usually done for drag & drop is not recommended with Angular. Instead, clone your object model.

Let's say you display items in an <UL> and have another dragged item visible only while dragging:

<ul>
    <li ng-repeat="item in items" class="{{item.shadow}}">{{item.text}}</li>
<ul>
<div ng-show="draggedItem != null">{{draggedItem.text}}</div>

and in the controller, make a copy of the item to drag into draggedItem:

$scope.items = [{text:"First"}, {text:"Second"}];
$scope.shadowItem = null; // Item at the original position
$scope.draggedItem = null; // Clone item being moved

$scope.dragStart = function(item) {
    $scope.shadowItem = item;
    $scope.draggedItem = angular.copy(item);
    item.shadow = "shadow"; // set a CSS class to change its look
    // From now on, the DIV is dragged around
}

$scope.drop = function() {
    // Save the new item position
    $scope.draggedItem = null; // Makes the dragged clone item disappear
    $scope.shadowItem.shadow = ""; // give the item its normal look back
}
Sign up to request clarification or add additional context in comments.

2 Comments

What am I doing is creating the "Actions". And every "Action" is different. So I've got for example UndoAction or ShowAllAction and so on. All of thous has carries different funtionality and has different graphical representation (these are different directives). What i want to do is similar to draggable skills in World of Warcraft. I know it's not recommended but I don't see any other solution.
All items you are moving are Actions. It doesn't matter that they have different graphical representations. You can put inside the <li> all the representations, each with its conditional attribute: ng-show="item.kind=='UndoAction'" for the first, ng-show="item.kind=='ShowAllAction'" for the next, etc. Then you can apply my method above.
3

I had the same issue wrapping a library which cloned my nodes. This is my solution:

angular.module('my-module')
.directive('mqAllowExternalClone', function($compile) {
  return {
    link: link,
  };

  function link(scope, elem, attr) {
    var element = elem[0];
    var original = element.cloneNode;
    element.cloneNode = patch;

    function patch(deep) {
      var clone = original.call(element, deep);

      // You can remove this two lines and the result
      //   will be more or less the same.
      // In my case I need it for other reasons
      clone.removeAttribute('mq-allow-external-clone');
      clone.cloneNode = patch;

      $compile(clone)(scope);
      return clone;
    }
  }
});

https://gist.github.com/amatiasq/ae6fce9acf74589ef36d

2 Comments

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
Yes, I thought of it but the idea was exactly that, if I improve or fix any bug on it the link will have the last version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.