The functionality of CDK Drag Drop is not accurately adjusting the placement of images

I have implemented an image gallery and am working on rearranging the position of the images using the Drag & Drop cdk library.

However, I am facing an issue where the swapping of images does not always occur correctly; sometimes when attempting to exchange the first image with the second, the swap does not happen as expected.

Is there a way to ensure smooth functionality for both horizontal and vertical repositioning of the images?

Furthermore, I would like to know if there is a method to initiate dragging only when the image is contained within the mdc-image-list - with-text-protection class.

Thank you in advance!

Check out the DEMO here

.HTML

<ul class="mdc-image-list my-image-list" style="padding-left: 10px;padding-right: 10px;" cdkDropList [cdkDropListData]="data"
           (cdkDropListDropped)="drop($event)">
    <ng-container *ngFor="let product of data; let j = index;">
      <li class="mdc-image-list__item" cdkDrag>
        <div class="mdc-image-list__image-aspect-container">
          <ng-container *ngIf="product.image == null; else productImage">
            <img src="" class="mdc-image-list__image imagenotfound">
          </ng-container>
          <ng-template #productImage>
            <img [src]="product.image" class="mdc-image-list__image">
          </ng-template>
        </div>
        <div class="mdc-image-list--with-text-protection">
        <div class="mdc-image-list__supporting mdc-image-list__supporting">
        <span class="mdc-image-list__label">{{product.name}}</span>
        </div>
        </div>
      </li>
    </ng-container>
  </ul>

.ts

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
      );
    }
  }

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

Answer №1

To enable drag and drop in a grid, I have found that each element of the grid needs to be a cdkDropList.

Advertisement: The elements do not move while dragging.

Since the data of each cdkDropList will consist of an object, the data we want to transport and the index.

[cdkDropListData]="{item:product,index:j}"

Therefore, our dropEvent function modifies the array data based on these values.

  drop(event: CdkDragDrop<any>) {
    this.data[event.previousContainer.data.index]={...event.container.data.item}
    this.data[event.container.data.index]={...event.previousContainer.data.item}
    event.currentIndex=0;
  }

We are not required to use drop as shown in the examples. Keep in mind that all we want is to modify an array.

Another thing to do is to ensure that the "dragPlaceholder" becomes an empty div.

<div cdkDrag>
     ....
    <div  *cdkDragPlaceholder></div>
</div>

The HTML structure may seem complex due to the nature of the mdc-image-list. It's crucial to note that all cdkDropLists must be enclosed in a div ckdDropListGroup.

<div cdkDropListGroup>

    <ul class="mdc-image-list my-image-list" style="padding-left: 10px;padding-right: 10px;">
        <ng-container *ngFor="let product of data; let  j = index;">
            <li class="mdc-image-list__item" cdkDropList [cdkDropListData]="{item:product,index:j}"
                cdkDropListOrientation="horizontal" (cdkDropListDropped)="drop($event)">
                <div cdkDrag>
                    <div class="mdc-image-list__image-aspect-container">
                        <ng-container *ngIf="product.image == null; else productImage">
                            <img src="" class="mdc-image-list__image imagenotfound">
          </ng-container>
                            <ng-template #productImage>
                                <img [src]="product.image" class="mdc-image-list__image">
          </ng-template>
                    </div>
                    <div class="mdc-image-list--with-text-protection">
                        <div class="mdc-image-list__supporting mdc-image-list__supporting">
                            <span class="mdc-image-list__label">{{product.name}}</span>
                        </div>
                    </div>
                    <div class="example-custom-placeholder" *cdkDragPlaceholder></div>
                </div>
            </li>
        </ng-container>
    </ul>
</div>

Here is your forked stackblitz

NOTE: For a simpler example, check out this other stackblitz

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

Encountering an unexpected token error while trying to compile a Typescript file to Javascript, even though it had previously worked

In my Typescript project, I usually run it using "ts-node". $ ts-node .\src\index.ts it works =) However, I wanted to compile it to Javascript, so I tried the following: $ tsc $ node .\src\index.js Unfortunately, I encountered the f ...

Issue with React not displaying JSX when onClick Button is triggered

I've recently started learning React and I'm facing a problem that I can't seem to figure out. I have a basic button, and when it's clicked, I want to add another text or HTML element. While the console log statement is working fine, th ...

Developing applications using the combination of Vue.js, JSX, and

While I have no issues using TypeScript with single file components (.vue files), I encountered problems when attempting to use it with JSX files. Two errors arise, one in my index.ts file. I'm uncertain if there was a mistake made in my configuration ...

What is the best way to create an interactive experience with MapLibre GL in Full Screen mode?

Hello, I am seeking a solution to create a map with the interactive option set to false, but once in full screen mode, I need this parameter to be true. Do you have any suggestions or ideas on how to achieve this? const _map = new MapGL({ contai ...

crafting connections in 3D using TypeORM (ORM)

I attempted to construct a database schema involving users, groups, documents, and permissions. Users can be part of multiple groups Groups can have multiple users Users can possess permissions for documents Groups can have permissions for documents Perm ...

The type 'Observable<unknown>' cannot be assigned to type 'Observable<Something>'

I am a beginner with Angular and Firebase, facing an issue while attempting to import of from rxjs and returning null using switchMap in my auth.service.ts. import { ActivatedRoute } from '@angular/router' import { Observable, of } from 'r ...

How can I gather information from members who have already signed up?

I have a form that submits data to the Angular Firebase database. Once the form is submitted, I want to display the previously submitted data in the form if the user signs in again. Below is my .ts file: import { Component, OnInit } from '@angular/c ...

Encountered an error: Object(...) function not defined when using React, Formik, and Webpack

I have encountered an issue while trying to use both Formik and React-Form-Hooks in my project. Despite using Typescript as my language and Babel as the transpiler, both libraries throw the same error when compiled. Uncaught TypeError: Object(...) is not ...

What steps do I need to take to export my TypeScript declarations to an NPM package?

I have multiple repositories that share similar functionality. I want to export type declarations to an NPM package so I can easily install and use them in my projects. Within the root directory, there is a folder called /declarations, containing several ...

Can we verify the availability of an Angular library during runtime?

I am in the process of creating a custom Angular library, let's name it libA, which has the capability to utilize another Angular library, named libB, for an optional feature. Essentially, if the Angular application does not include libB, then the fea ...

Adaptively linking to the property of a deeply nested object

Attempting to bind to a property of a nested object using [(ngModel)], but facing the challenge that the path to the property is dynamically set. Consider the following three classes: class A { p1: C constructor() { p1 = new C("A") } } class B { p2: ...

Potential 'undefined' object detected in Vuex mutation using TypeScript

Currently, I am diving into learning Vue.js alongside Vuex and TypeScript. While working on my application, I encountered an error stating "Object is possibly 'undefined'" within the Vuex Store. The error specifically arises in the "newCard" mut ...

I encountered an error in my Spring Boot application where I received a TypeError: Cannot read properties of undefined (reading '0') related to the angular.min.js file at line 129

As I work on designing a login page using Angular in my Java Spring Boot application, I encounter an issue. When attempting to log into the panel page, the username and password are successfully sent to the application via the API controller and the user t ...

What is the best way to consistently position a particular row at the bottom of the table in AG-grid?

I have successfully implemented a table using AG-grid. Here is the code snippet: .HTML <ag-grid-angular #agGrid style="width: 100%; height: 100%; font-size: 12px;" class="ag-theme-alpine" [rowData]=&quo ...

Leveraging Angular's catchError method to handle errors and return

One of my challenges involves a model class that represents the server response: class ServerResponse { code: number; response: string; } Whenever I make api calls, I want the response to always be of type Observable<ServerResponse>, even in ...

Getting the Value of a CSS Class through Form Name in Angular

I am attempting to retrieve the class name of a form control using the Form Name both in HTML and in the Class file The code snippet below functions correctly and shows the value of the control {{ModelForm.value.firstName| json}} However, when I try to d ...

The issue encountered during a POST request in Postman is a SyntaxError where a number is missing after the minus sign in a JSON object at position 1 (line 1

Running my API in a website application works flawlessly, but encountering SyntaxError when testing it in Postman - specifically "No number after minus sign in JSON at position 1" (line 1 column 2). The data is correctly inputted into the body of Postman a ...

Unable to access res.name due to subscription in Angular

Right now, I am following a tutorial on YouTube that covers authentication with Angular. However, I have hit a roadblock: The code provided in the tutorial is not working for me because of the use of subscribe(), which is resulting in the following messag ...

Can someone confirm if I am importing this png file correctly? I am encountering an error with Vite, here is my code

Error: TypeScript+ React + Vite [plugin:vite:import-analysis] Failed to find import "./assets/heropic.png" in "src\components\Hero.tsx". Are you sure the file exists? Hello fellow developers! I am new to working with react and typescript. Curren ...

Creating an Increment and Decrement Button for Products in Angular and Ionic 3

I have gone through various tutorials, but there is still some confusion. I am attempting to create an increment and decrement button, but so far I have not been successful. Within an ion-list, I have multiple h3 elements. Here is a snippet of my view: ...