Dragula drag and drop in a single direction with Angular 2 copy functionality

Attempting to utilize ng2 dragula for one-way drag and drop with copy functionality. Below is the template I am working with:

`<div>
   <div class='wrapper'>
     <div class='container' id='no-drop' [dragula]='"first-bag"'>
       <div>Drag/drop item 1</div>
     </div>
     <div class='container' [dragula]='"first-bag"'>
       <div>Drag/drop item 2</div>
     </div>
   </div>
 </div>` 

The 'copy' option has been enabled in my component as shown below:

constructor(private dragulaService: DragulaService) {
dragulaService.setOptions('first-bag', {
  copy: true
});

If I set 'moves' to false, dragging becomes disabled entirely. How can I restrict the movement from left to right only?

Answer №1

Shortly after making the post, I was able to discover the solution!

   constructor(private dragulaService: DragulaService) {
    dragulaService.setOptions('first-bag', {
      copy: true,
      moves: function (el, container, handle) {
        return container.id !== 'no-drop';
      }
    });

Answer №2

When using dragula, the default behavior allows users to drag elements from one container and drop them into another. If the element is dropped outside of any containers, the event will be canceled gracefully based on the revertOnSpill and removeOnSpill options.

In the example below, users can drag items from left to right and vice versa. This code snippet should be implemented in HomePage.component.html:

 <div class="wrapper"> <div class="container master" [dragula]="'editor-bag'" [dragulaModel]="q1">

      <div *ngFor="let item of q1" class="box">
      {{item}}
      </div>
 </div>
 <div class="container" [dragula]="'editor-bag'">
 </div> 

Furthermore, create HomePageComponent.ts file and include an `accepts` method with the following signature: (el, target, source, sibling).

import { DragulaService, DragulaDirective } from 'ng2-dragula/ng2-dragula';
import { Router, Route, ActivatedRoute } from '@angular/router';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home-page',
  templateUrl: './home-page.component.html',
  styleUrls: ['./home-page.component.css'],
})
export class HomePageComponent implements OnInit {
  q1 = [];
  q2 = [];
  static _debug: boolean = false;
  _debug: boolean = HomePageComponent._debug;
  constructor(private dragulaService: DragulaService, private router: Router, private route: ActivatedRoute) { 
    for (var i = 0; i < 10; i++) {
      this.q1.push("1. <" + i + ">");
      //this.q2.push("2. <" + i + ">");
    }

      dragulaService.setOptions('editor-bag', {      
      accepts: function (el, target, source, sibling) {
        var fn_debug = true;
        var acceptAll = false;

          if (this._debug || fn_debug) {
            console.log("accepts() start el, target, source, sibling");
            console.log({ el, target, source, sibling });
          }
          if (target.classList.contains('master')) {
            return false;
          }
          if (sibling == null) {
            return (target.children.length == 0);
          }
          var name: string = el.innerText;
          return false;
        },

      direction: 'vertical',             
      copy: function (el, source) {
        if (this._debug) {
          console.log("copy() start");
          console.log(el);
          console.log(source);
          console.log("copy() stop");
        }
        return source.classList.contains('master');
      },                       
      copySortSource: false,             
      revertOnSpill: false,              
      removeOnSpill: true,              
      mirrorContainer: document.body,    
      ignoreInputTextSelection: true     
    })
  }
  ngOnInit() {

      this.dragulaService.drag.subscribe((value: any) => {
        if (this._debug) {
          console.log("drag start");
          console.log(value);
          console.log("drag stop");
          console.log(`drag: ${value[0]}`);
        }
       // this.onDrag(value.slice(1));
      });

      this.dragulaService.drop.subscribe((value: any) => {
        console.log(`drop: ${value[0]}`);
        //this.onDrop(value.slice(1));
      });

      this.dragulaService.over.subscribe((value: any) => {
        if (this._debug) { console.log(`over: ${value[0]}`); }
       // this.onOver(value.slice(1));
      });

      this.dragulaService.out.subscribe((value: any) => {
        if (this._debug) { console.log(`out: ${value[0]}`); }
        //this.onOut(value.slice(1));
      });
    }

}

Sharing my solution here might benefit others who come across similar challenges.

Answer №3

My preference is to utilize the accepts function over the moves function.

The moves function has the potential to halt the movement of items from the container, whereas the accepts function determines the validity of the target container.

accepts: function (el, target, source, sibling) {
              // your condition
            },

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for developing a custom pipe in Angular 12 with ngx-translate and internationalization support?

I've been working on internationalization for my angular project, which is an admin portal using @ngx-translate. Unfortunately, I've hit a roadblock and need to start over with the internationalization task. Any suggestions on how to approach thi ...

Troubleshooting Issue with Angular 5: Inability to Hide Elements for Non-Authenticated Users

Below is the code from app.component.html <nav class='navbar navbar-default'> <div class='container-fluid'> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-targ ...

Tips for patiently anticipating the completed response within an interceptor

Using the interceptor, I want to display a loading spinner while waiting for subscriptions to complete. This approach works well in individual components by showing and hiding the spinner accordingly: ngOnInit() { this.spinnerService.show(); this. ...

Executing installed packages using npm: A step-by-step guide

Recently, I have encountered a confusing issue in my coding journey. In Python, I got used to installing packages and using them right away without any hiccups. For example, with SpotDL, everything worked seamlessly. However, things took a different turn w ...

Issue encountered when assigning a CSS class to Angular component

My module contains a table structure with specific components. Here is the source code for table.component.html: <table border=1> <theader></theader> </table> The source code for theheader.component.html is as follows: <thea ...

Choosing the specific columns to be shown in the Kendo Angular grid

Will there be an interface available in the grid for users to select which columns are displayed, or is this a feature that will be introduced in the upcoming September release? ...

Angular Bounce Effect: Adding a Touch of Fun to Your

I'm utilizing the angular animation plugin ( https://www.npmjs.com/package/@angular/animations ) in my project. I am now looking to incorporate a bouncing effect when adding or removing items from an array. Below is the template snippet: <h2 *ngI ...

The type 'void' cannot be assigned to the type 'ReactNode'

Having trouble with the total amount calculation due to the nature of the calculateTotal function import CartItem from "./CartItem" import {CartItemType} from '../App' import {Typography,Stack} from '@mui/material'; type Props ...

AngularJS - Sending event to a specific controller

I am facing an issue with my page where a list of Leads each have specific actions that are represented by forms. These forms can be displayed multiple times on the same page. Each form has its own scope and controller instance. After submitting a form, an ...

It is not possible to transform Next.js into a Progressive Web App (P

Can someone assist me with PWA implementation? I tried running npm run build, but it was unsuccessful. > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cdbaacbface0abbfa2a3b98dfde3fce3fd">[email protected]</a> ...

The MUI DataGrid's onCellEditStop event triggers when a cell's value is

When using MUI DataGrid, I encountered an issue where the value of a previously edited cell changes when editing another cell. I read that using onCellEditCommit as a solution, but since it's deprecated, I'm seeking an alternative fix. const ha ...

Step-by-step guide for setting up automatic Tslint in IntelliJ

When working on an Angular project in Intellij, I often encounter numerous tslint errors while coding. Is there a command within Intellij that can automatically fix all of these lint errors? ...

What type of class is considered a mixin in programming?

Struggling to determine the type of a typescript mixin class without using a workaround method. Here are a couple of examples: type Constructor<T = {}> = new(...args: any[]) => T; function MyMixin<T extends Constructor>(BaseClass: T) { r ...

The act of exporting an enum from a user-defined TypeScript path leads to the error message "Module not

I have set up a custom path as explained in this particular discussion. "baseUrl": ".", "paths": { "@library/*": [ "./src/myFolder/*" ], } Within this module, I am exporting an Enum. export enum EN ...

Demonstrating a feature in a custom Angular Material dialog box

I have a reusable custom Material UI Dialog that I want to utilize to show different components. For instance, I would like to display a Login component on one occasion and a Registration component on another. However, the issue arises when I assign my com ...

The 'Key' identifier is not valid for indexing the 'Object' data type

Currently attempting to incorporate functional pluck with a specific sound type, but encountering an issue: function extract<Object extends {}, Key = keyof Object>(key: Key): (o: Object) => Object[Key] { return object => object[key]; } Erro ...

Please provide TypeScript code for a React wrapper function that augments a component's props with two additional functions

During the course of my project, I implemented a function wrapping React component to incorporate undo/redo functionality using keyboard shortcuts Ctrl+Z and Shift+Ctrl+Z. Here is an example: import React from 'react'; interface WithUndoRedoProp ...

Passing index value using navigateByUrl method

I have developed a home component and a view component to display different levels of employee details. The home component presents basic information, while the view component shows comprehensive details. The code in my home.component.html file looks like ...

Basic Karma setup with Typescript - Error: x is undefined

I am trying to configure a basic test runner using Karma in order to test a TypeScript class. However, when I attempt to run the tests with karma start, I encounter an error stating that ReferenceError: Calculator is not defined. It seems like either the ...

Can an Observable be created that emits an array produced by awaiting asynchronous methods?

I've encountered an issue with the following method: get fileResults$(): Observable<File[]> { return this.ngRedux.select<ICommunicationState>('communication').pipe(map(newState => { const files: File[] = []; ...