CDK Drag and Drop capability for lists within lists

I am trying to figure out how to display users and their corresponding information in a structured way. Each user should be presented in their own column, with the associated information displayed within that column. I have been attempting to drag and drop the users and information between columns, vertically and horizontally, but have been facing some challenges.

Can someone assist me in solving this issue so that I can easily move the cards from one user's column to another?

For example, I want to be able to move a card with the text "Expand" from the column named Name1 to the column named Name2.

Thank you

DEMO

https://i.sstatic.net/JY9NP.png

html

<div style="width:100%; height:100%; display:flex; justify-content:center">
<div *ngFor="let usr of Users" style="width: 20%;">
  <div class="card">
    <div class="card-header" style="display: flex; align-items: center; justify-content: center;">
      <span>{{usr.name}}</span>
    </div>
    <div class="card-body" style="height:100%" cdkDropList
      cdkDropListOrientation="vertical" [cdkDropListData]="Info"
      (cdkDropListDropped)="drop($event)">    
      <div *ngFor="let item of Info">
        <div *ngIf="usr.id == item.idUser" cdkDrag>
          <div class="card">
            <div class="card-header" style="padding: 0px;">
             <span>{{item.text}}</span>
            </div>
            <div class="card-body" style="padding: 0px;position: relative;">
          <span>{{item.text}}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
</div>

.ts

  Users = [
    { id: 1, name: "Name1" },
    { id: 2, name: "Name2" },
    { id: 3, name: "Name3" }
  ];

  Info = [
    { idUser: 1, text: "Expand1" },
    { idUser: 1, text: "Expand11" },
    { idUser: 2, text: "Expand2" },
    { idUser: 2, text: "Expand22" },
    { idUser: 3, text: "Expand33" },
    { idUser: 3, text: "Expand33" }
  ];

  drop(event: CdkDragDrop<string[]>) {
    console.log("TO", event.previousContainer.data[event.previousIndex]);
    console.log("FROM", event.previousContainer.data[event.currentIndex]);
    if (event.previousContainer === event.container) {
      moveItemInArray(
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    } else {
      transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    }
  }

Answer №1

If you want to address this issue, consider making the following adjustments to your approach:

  1. Ensure that each user has an array of UserInfo items instead of relying on a single data source.
  2. Implement cdkDropListGroup on the container element that holds all cdkDropList components.

That's all you need to do!

import {
  Component
} from "@angular/core";
import {
  CdkDragDrop,
  moveItemInArray,
  transferArrayItem
} from "@angular/cdk/drag-drop";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  Users = [{
      id: 1,
      name: "Name1",
      items: [{
        idUser: 1,
        text: "Expand1"
      }, {
        idUser: 1,
        text: "Expand11"
      }]
    },
    {
      id: 2,
      name: "Name2",
      items: [{
        idUser: 2,
        text: "Expand2"
      }, {
        idUser: 2,
        text: "Expand22"
      }]
    },
    {
      id: 3,
      name: "Name3",
      items: [{
        idUser: 3,
        text: "Expand33"
      }, {
        idUser: 3,
        text: "Expand33"
      }]
    }
  ];

  drop(event: CdkDragDrop < string[] > ) {
    if (event.previousContainer === event.container) {
      moveItemInArray(
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    } else {
      transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    }
  }
}
<div style="width:100%; height:100%; display:flex; justify-content:center" cdkDropListGroup>
  <div *ngFor="let usr of Users" style="width: 20%;">
    <div class="card">
      <div class="card-header" style="display: flex; align-items: center; justify-content: center;">
        <span>{{usr.name}}</span>
      </div>
      <div class="card-body" style="height:100%" cdkDropList id="{{usr.id}}" cdkDropListOrientation="vertical" [cdkDropListData]="usr.items" (cdkDropListDropped)="drop($event)">
        <div *ngFor="let item of usr.items">
          <div cdkDrag>
            <div class="card">
              <div class="card-header" style="padding: 0px;">
                <span>{{item.text}}</span>
              </div>
              <div class="card-body" style="padding: 0px;position: relative;">
                <span>{{item.text}}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Check out this stackblitz link based on your original code.

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

The contrast between FormData and jQuery's serialize() method: Exploring the distinctions

Recently I came across a situation where I needed to submit a form using AJAX. While researching the most efficient method, I discovered two popular approaches - some developers were utilizing jQuery#serialize() while others were opting for FormData. Here ...

Is there a way to trigger the opening of a new file or page when a CSS animation comes to an end?

Is there a way to delay the loading of a function or page until after an animation has finished running in JavaScript, HTML, and CSS only? For instance, I'd like to run an animation first and then have a different website or content load afterwards fo ...

Unable to simulate axios instance in a Typescript environment

After reading through this particular article, I decided to attempt writing a unit test while simulating Axios (with Typescript). Incorporating an Axios instance to define the baseUrl. // src/infrastructure/axios-firebase.ts import axios from 'axios ...

Experimenting with the speechSynthesis API within an iOS webview application

I'm currently working on developing an app that features TTS capabilities. Within my webview app (utilizing a React frontend compiled with Cordova, but considering transitioning to React Native), I am implementing the speechSynthesis API. It function ...

Should the hourly charge schedule be based on user input and be created from scratch or utilize existing templates?

I have hit a roadblock while creating a charging schedule based on user input for my project. I am debating whether to search for and modify an existing plugin or develop it from scratch. The schedule involves solar charging electric cars between 7am and ...

How can I use "Lite-Server" with NPM start to showcase my index.cshtml file on the browser?

Currently, I am trying to navigate the world of Visual Studio Code and figure out how to run/compile my project. Starting a new project in Visual Studio was simple enough, but now that I'm working with Visual Studio Code, I find myself struggling to s ...

angular2: The element 'Validators' is not recognized

When working with Angular2, I encountered an error in Visual Studio Code that is displayed with the following message: enter image description here Here is the content of my tsconfig.json file: { "compilerOptions": { "target": "es5", "module" ...

Reduce the file size of CSS and JS files for Magento

We are facing an issue with minifying CSS and Javascript for our Magento website. Currently, the size of our website is 1.1 MB and we aim to reduce it to 1 MB or even lower if possible. I tried using the "CSS Settings" and "Javascript Settings" functions ...

When Ajax attempts to run a PHP page, it redirects me to a different page

My goal is to create a live chat feature using PHP, MySQL, and AJAX. I have almost got it working perfectly, but I'm stuck on how to submit the chat message without refreshing the page. I have a PHP page called sendchat.php that takes input data and s ...

Issue with setState not being triggered within axios POST request error handling block

I am in the process of setting up an error handler for a React Component called SignupForm.js, which is responsible for handling user registrations. Specifically, I am working on implementing a handler to deal with cases where a user tries to sign up with ...

Annoying glitch when using http get in Ionic (version 3.19.0)

Issue: Having trouble with Ionic's http get function, as I keep running into this error message: Typescript Error Expected 1-2 arguments, but got 3. The line causing the problem seems to be similar to this: this.http.get('http://127.0.0.1 ...

Transitioning from using sendfile() to sendFile() function within the Express framework

Here is the code snippet I am using: router.get('/image',(req,res,next)=>{ const fileName = "path_to.jpg" res.sendfile(fileName,(err)=>{ if (err) { next(err); } else { console.log('Sent:', fileName); } ...

Issue with Cloud Code function preventing data from being saved

After successfully testing this code in Angular and getting the correct responses in console.log, I decided to migrate it to cloud code. Since the function manipulates data in the user table, I had to use the master key and implement it in cloud code. Howe ...

Problem with loading messages in VueI18n locale

Utilizing the vueI18n package for language localization in our application, we fetch the locale messages object via an api call. Within our config file, we have specified the default language which is used to load the locale before the creation of app.vue. ...

The equation of jquery plus ie7 results in an undefined value

I am experiencing a strange issue in IE7 with a jQuery script. This problem seems to only occur in IE7. In summary, when I check the console window, it shows that jQuery is not defined - even though I have loaded jQuery (version 1.7.1) from my disk and can ...

Retrieving values from a jQuery object array using keys rather than array indices

I am facing a challenge where I need to extract values from an object returned through $.post, but the order of the arrays can vary. Therefore, I must retrieve them based on their keys which are nested inside the array. An example is provided below. { Id: ...

ways to coordinate two subscriptions so that one initiates only when the other one emits

Currently, I am developing an Angular application with a specific scenario. I have an observable signal named dataFetchedEvent$, which indicates that data has been fetched from a remote location. Additionally, there is a form that relies on this remote dat ...

An issue occurred while attempting to retrieve an access token in NodeJs, resulting in 500 failures. The error message displayed was: "connect ECONNREFUSED" at process._tickCallback (node

I'm trying to authenticate users using Passport's GoogleStrategy, but I keep encountering the following error. Can anyone assist me? Code passport.use(new GoogleOAuth2Strategy({ clientID : configAuth.googleAuth.clientID, clientS ...

ReactJS: Checkbox status remains consistent through re-rendering of Component

I have developed a JSfiddle example Initially, this fiddle displays a list of checkboxes based on the passed props to the component. When you click the Re-render button, the same component is rendered with different props. Now, please follow these steps- ...

When using the "Content-Disposition" header with the value "inline;filename=" + fileName, it does not necessarily guarantee that PDF files will be displayed directly

When a link is clicked, I want the PDF file to first show in a new tab as a preview before allowing users to download it. I researched and found advice suggesting that including these two headers would achieve this: Response.AddHeader("Content-Dispositio ...