John w.
John w.

Reputation: 531

How to implement drag & Drop on an image, changing its position

I developed a slider that presents me with several images.

At the top (large image and where the slider is located) I have the initial image as the main image.

At the bottom I have the secondary images (see image below).

Is there a way to drag an image to the div that contains the slider in order to change the order? Basically I intend to exchange an image that is in the small box with the first image in the large box.

Can I change the order of the small images horizontally, too?

Thank you.

DEMO - Stackblitz

code

 <div class="col-md-6" style="overflow-y: auto;"  (cdkDropListDropped)="drop($event)">
        <div class="drop" [style.border-width.px]="imagens.length > 0 ? 0: 3">
          <div class="abc">
              <ngb-carousel style="outline: none;" id="carousel" #carousel *ngIf="imagens" (slide)="change($event)">
                <ng-template *ngFor="let imgIdx of imagens; let i = index" [id]="i" ngbSlide>
                  <div class="picsum-img-wrapper">
                    <img [src]="imgIdx.Imagem" style="border-radius: 8px;" class="img-responsive Images">
                      </div>                    
                </ng-template>              
              </ngb-carousel>            
          </div>
        </div>
        <div class="row">
          <div class="Upcard" *ngFor="let imgIdx of imagens | slice:1" >
            <img class="img-responsive" [src]="imgIdx.Imagem" style="width: 100%; height: 100%">
          </div>
        </div>
      </div>

I tried to use this, adding in the html cdkdrag, but no, it didn't work.

   drop(event: CdkDragDrop<string[]>) {
     moveItemInArray(this.imagens, event.previousIndex, event.currentIndex);
   }

   dropBig(event: CdkDragDrop<string[]>) {
     moveItemInArray(this.imagens, event.previousIndex, 0);
   }

Image

Upvotes: 1

Views: 3946

Answers (1)

Eliseo
Eliseo

Reputation: 57929

the cdk drag and drop it's usefull to drag between two cdkDropList. Normally it's used to interchange values of two arrays (the cdkDropListData of the cdkDropList). So you need defined first the cdkDropList and the elements dragables (cdkDrag)

So, first change the angular.json to use the cdk 8.2.3, -you're using Angular 8, not mixed versions-

"@angular/cdk": "^8.2.3",

Then create two arrays, imagens and imagens2(*) and change your .html as -see where there are the cdkDropList and the cdkDrag-

<div class="col-md-6" style="overflow-y: auto;">
    <div class="drop" [style.border-width.px]="imagens.length > 0 ? 0: 3">
        <div class="abc" cdkDropList #dropList="cdkDropList" cdkDropListOrientation="horizontal"
            [cdkDropListData]="imagens" 
            [cdkDropListConnectedTo]="[dragList]" 
            (cdkDropListDropped)="drop($event)">
            <ngb-carousel data-interval="false" style="outline: none;" id="carousel" #carousel *ngIf="imagens"
                (slide)="change($event)">
                <ng-template *ngFor="let imgIdx of imagens; let i = index" [id]="i" ngbSlide>
                    <div class="picsum-img-wrapper" cdkDrag [cdkDragDisabled]="true">
                        <img [src]="imgIdx.Imagem" style="border-radius: 8px;" class="img-responsive Images">
                      </div>
                </ng-template>
            </ngb-carousel>
        </div>
    </div>

    <div class="row" cdkDropList #dragList="cdkDropList" cdkDropListOrientation="horizontal"
        [cdkDropListData]="imagens2" 
        [cdkDropListConnectedTo]="[dropList]" 
        (cdkDropListDropped)="drop($event)">
        <div class="Upcard" *ngFor="let imgIdx of imagens2" cdkDrag>
            <img class="img-responsive" [src]="imgIdx.Imagem" style="width: 100%; height: 100%">
          </div>
        </div>
    </div>

well, in general the function drop is like

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

But this make that when you drop an image fron imagens2 to imagens, the dragged imagen is added to the array imagens and remove from the array imagens2 -you move the images-

If you want to exchange the two images you simple use splice. Remember it's only change two arrays

  drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    } else {
      const imagen = { ...(event.container.data[event.currentIndex] as any) };
      const previousImagen = {
        ...(event.previousContainer.data[event.previousIndex] as any)
      };
      event.container.data.splice(event.currentIndex, 1, previousImagen);
      event.previousContainer.data.splice(event.previousIndex, 1, imagen);
    }
  }

Well if you want not "interchange" the two images else remove from the slider the image dragged, change the function drop. Remember event.container.data is the array where you drop the imagen (in the event.currentIndex) and event.previousContainer.data is the array from you drag the imagen (the event.previousIndex give you the imagen dragged)

see your forked stackblitz

(*) I think in two differents arrays, I "clone" your array using

  imagens2 = this.imagens.map(x => ({ ...x }));

Upvotes: 3

Related Questions