7

I have a Angular2 component using ng2-dragula to drag/drop like this:

@Component({
  selector: 'my-comp',
  directives: [
    Dragula
  ],
  viewProviders: [
    DragulaService
  ],
  template: `
    <div class="my-div">
      <div *ngFor="#item of items" [dragula]='"card-bag"' [dragulaModel]='items'>
      ...
      </div>
    </div>
  `
})

My issue: if I create multiple "my-comp" component, item inside "card-bag" can not drag/drop across these component although they have the same bag name. These item are only able to drag/drop inside it owned component.

Do we have any configs for drag/drop across components, or this is ng2-dragula limitation?

Thanks.

10
  • Hopefully someone else can chime in but I think you would have to make this a global service within bootstrap to get that kind of functionality. The problem is when you import this within each component seperately, it makes a new instance of it for each component. If you add it to your bootstrap it is a global attachment for all of your components. I hope this answers what you were asking about! Commented Mar 14, 2016 at 7:13
  • @MorganG: thank you. I also think about that idea, but I hope we will have an official or a better solution for this problem.. Commented Mar 14, 2016 at 17:45
  • One way I made a work around for this, is I have a service that's a global variable with a list of observables and I just reference that observable or object every time I need it in other pieces of my application. Whenever I need another global observable or object I just add it to that service. But I agree it seems a bit backwards to have to do everything that way. Commented Mar 14, 2016 at 20:40
  • @MorganG can you elaborate on this with a bit of code? I am trying to do the same, but can't figure out how to get it globally. Commented Mar 24, 2016 at 13:36
  • @MorganG do u have any plnkr for this? i have this problem to except I have thumbnails of components and I want load corresponding components on dragging of thumbnails Commented Apr 28, 2016 at 10:53

2 Answers 2

10

If you are not using [dragulaModel] then drag and drop between nested components works well as long as you only set viewProviders: [ DragulaService ] once in the top/root component.

Remember not to set viewProviders: [ DragulaService ] in other components as it creates new instances for every component.

Edit: Recently I have implemented the given scenario using ng2-dnd npm package. Its better than ng2-dragula and offers easy object passing and other things. It might Solve your issue.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the ng2-dnd mention, that is a great find, easy to use, works great!
Thanks , the ng2-dnd rocks , my whole requirement was to have an ability to carry data across droppable and draggable divs , ng2-dnd is perfect for that , I would recommend anyone dnd over dragula.
2

I got a tree structure drag and drop working like this:

Top level component

  • CSS ViewEncapsulation.None, include any css here
  • Dragula Directive
  • DragulaService ViewProvider
  • Registering an accepts filter on the dragula service that stops items from being dropped inside themselves

    accepts: (el: Element, target: Element, source: Element, sibling: Element): boolean => {
     return !el.contains(target); // elements can not be dropped within themselves
    },
    
  • Registering a moves filter on the dragula service so that an entire item is moved together

    moves: (el: Element, container: Element, handle: Element): boolean => {
      // only move favorite items, not the icon element
      return el.tagName.toLowerCase() === 'mvp-navigation-item';
    },
    
  • Html template looks like this

    <div class="nav--favorites__root" [class.is-dragging]="isDragging" [dragula]="'favorites'" [dragulaModel]="favoriteLinks">
      <navigation-item *ngFor="let link of links" [link]="link">
      </navigation-item>
    </div>
    

Navigation item component

  • Dragula Directive
  • No DragulaService ViewProvider
  • Html template looks like this

    <a href class="list-group-item" linkActive="active" [linkTo]="link?.url" (click)="followLink($event, link)">
      <span class="glyphicon glyphicon-{{link?.icon ? link?.icon : 'unchecked'}}"></span>
      <span class="nav__label">{{link?.label}}</span>
    </a>
    <div *ngIf="link?.children" class="list-group list-group-inverse nav--favorites__submenu" [class.is-expanded]="link?.isExpanded" [class.is-empty]="link?.children?.length === 0" [dragula]="'favorites'" [dragulaModel]="link?.children">
      <navigation-item *ngFor="let childLink of link?.children" [link]="childLink">
      </navigation-item>
      <!-- the nav favorites items must be the first elements in the dragula container or the model sync gets confused -->
      <a class="btn btn-link toggle" (click)="link.isExpanded = !link.isExpanded; $event.preventDefault();"><span class="glyphicon glyphicon-triangle-{{link?.isExpanded ? 'top' : 'bottom'}}"></span></a>
    </div>
    

You'll need to style things to make the .nav--favorites__submenu visible as a drop target while dragging an item.

3 Comments

No Dragula directive in the child dragula throws error something like 'Dragula is not a native property'. It cannot launch any tag with [dragula] since no directives are specified. Not sure if your answer is right, I think not.
@BecarioSenior after RC5, directives are declared in the ngModule instead of the individual components. Besides that change, everything still works. Make sure that the DragulaService is declared in the top component or in the ngModule but not in the child components, since we want a single shared instance of the service.
This one work for me, but I can't find any way to drag for example 2 next items together. I have select mode, but I didn't have any idea how keep it together during drag mode...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.