angularjsdragulaangular-dragula

AngularJS-Dragula nested lists


TL;DR;
I need to drag in nested lists, and I can't get it to work. I've compiled a quick example over at Plunkr.

I have dynamic nested sets with no defined depth, and I need to be able to sort them within their own parent-container only. But since the parent is also being dragged around, whenever you pick up a child, the entire tree is being dragged around.

function ListItemController($scope, dragulaService) {
  var self = this;

  this.$onInit = function() {
    dragulaService.options( $scope, this.item.id, {
      removeOnSpill: false,
      moves: function (el, source, handle, sibling) {
        console.info(el, target, source, sibling);
        return el.id === self.item.id; // elements are always draggable by default
      },
      accepts: function (el, target, source, sibling) {
        console.info(el, target, source, sibling);
        return true; // elements can be dropped in any of the `containers` by default
      },
      invalid: function (el, handle) {
        return el.id !== self.item.id; // don't prevent any drags from initiating by default
      },
    });

    if (this.item.children && this.item.children.length > 0) {
      $scope.$on(this.item.id + '.drag', function() {
        console.info(this.item.id + '.drag', arguments);
      });
    }
  }; 
}

The documentation mentions to use the moves function to create a handle, which would probably help me out, but I never get a log from that function, nor from the accepts function.

I've tried using $postLink and a watcher on $scope.$$dragula to ensure that it is initiated, and even a watcher on dragulaService.find($scope, self.item.id). None of it worked...


Solution

  • The problem lied in the way the library looks for the bag-name. This uses $scope.$eval. Meaning it tried to execute the name i gave it.

    <span id="{{$ctrl.item.id}}">{{ $ctrl.item.text }}</span>
    <ol dragula="{{$ctrl.item.id}}">
      <list-item ng-repeat="child in $ctrl.item.children" item="child"></list-item>
    </ol>
    

    Meaning this did not work, it initiated lists named 0, -1, etc...

    <span id="{{$ctrl.item.id}}">{{ $ctrl.item.text }}</span>
    <ol dragula="'{{$ctrl.item.id}}'">
      <list-item ng-repeat="child in $ctrl.item.children" item="child"></list-item>
    </ol>
    

    But by adding single-quotes around the statement, $scope.$eval saw it as a string, and thus made the entire thing work as expected.

    For the full code, check out: https://plnkr.co/edit/6h1HUb98wwspJ1KggISh?p=preview