Skip to content
Snippets Groups Projects
drop-list.component.ts 5.13 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { Component, Input } from '@angular/core';
    
    rhenck's avatar
    rhenck committed
    import { CdkDragDrop } from '@angular/cdk/drag-drop/drag-events';
    
    import {
      CdkDrag, CdkDropList, moveItemInArray, transferArrayItem
    } from '@angular/cdk/drag-drop';
    
    import { DropListElement } from './drop-list';
    import { FormElementComponent } from '../../directives/form-element-component.directive';
    
    rhenck's avatar
    rhenck committed
    
    @Component({
      selector: 'app-drop-list',
      template: `
    
        <div class="list-container">
    
          <!-- Border width is a workaround to enable/disable the Material cdk-drop-list-receiving-->
          <!-- class style.-->
    
          <div class="list"
    
               [class.dropList-highlight]="elementModel.highlightReceivingDropList"
               [style.border-color]="elementModel.highlightReceivingDropListColor"
               [style.border-width.px]="elementModel.highlightReceivingDropList ? 2 : 0"
    
               [style.color]="elementModel.fontProps.fontColor"
               [style.font-family]="elementModel.fontProps.font"
               [style.font-size.px]="elementModel.fontProps.fontSize"
               [style.font-weight]="elementModel.fontProps.bold ? 'bold' : ''"
               [style.font-style]="elementModel.fontProps.italic ? 'italic' : ''"
               [style.text-decoration]="elementModel.fontProps.underline ? 'underline' : ''"
               [style.backgroundColor]="elementModel.surfaceProps.backgroundColor"
    
               [style.display]="elementModel.orientation === 'horizontal' ? 'flex' : ''"
               [style.flex-direction]="elementModel.orientation === 'horizontal' ? 'row' : ''"
               cdkDropList
               [id]="elementModel.id"
               [cdkDropListData]="this"
               [cdkDropListConnectedTo]="elementModel.connectedTo"
               [cdkDropListOrientation]="elementModel.orientation"
               [cdkDropListEnterPredicate]="onlyOneItemPredicate"
               (cdkDropListDropped)="drop($event)">
    
            <ng-container *ngFor="let value of $any(elementModel.value)">
              <div class="item" *ngIf="!value.imgSrcValue" cdkDrag
                   [style.background-color]="elementModel.itemBackgroundColor"
                   (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()">
                <div *cdkDragPreview
                     [style.font-size.px]="elementModel.fontProps.fontSize"
                     [style.background-color]="elementModel.itemBackgroundColor">
                  {{value.stringValue}}
                </div>
                <div class="drag-placeholder" *cdkDragPlaceholder [style.min-height.px]="elementModel.fontProps.fontSize">
                </div>
                {{value.stringValue}}
    
              <img *ngIf="value.imgSrcValue"
                   [src]="value.imgSrcValue | safeResourceUrl" alt="Image Placeholder"
    
                   cdkDrag (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()"
                   [style.object-fit]="'scale-down'">
            </ng-container>
    
    rhenck's avatar
    rhenck committed
          </div>
    
          <mat-error *ngIf="elementFormControl.errors && elementFormControl.touched"
                     class="error-message">
            {{elementFormControl.errors | errorTransform: elementModel}}
          </mat-error>
    
    rhenck's avatar
    rhenck committed
        </div>
      `,
      styles: [
    
        '.list-container {display: flex; flex-direction: column; width: 100%; height: 100%;}',
    
    rhenck's avatar
    rhenck committed
        '.list {width: calc(100% - 4px); height: calc(100% - 4px); border-radius: 10px}',
        '.item {border-radius: 10px; padding: 10px;}',
    
        '.item {cursor: grab}',
        '.item:active {cursor: grabbing}',
    
    rhenck's avatar
    rhenck committed
        '.item:not(:last-child) {margin-bottom: 5px;}',
    
        '.error-message {font-size: 75%; margin-top: 10px;}',
    
        '.cdk-drag-preview {padding: 8px 20px; border-radius: 10px}',
    
    rhenck's avatar
    rhenck committed
        '.drag-placeholder {background-color: lightgrey; border: dotted 3px #999; padding: 10px;}',
        '.drag-placeholder {transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);}',
    
        '.cdk-drag-animating {transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);}',
    
        '.dropList-highlight.cdk-drop-list-receiving {border: solid;}',
        '.dropList-highlight.cdk-drop-list-dragging {border: solid;}'
    
    rhenck's avatar
    rhenck committed
      ]
    })
    export class DropListComponent extends FormElementComponent {
    
      @Input() elementModel!: DropListElement;
    
    rhenck's avatar
    rhenck committed
    
    
      bodyElement: HTMLElement = document.body;
    
      dragStart() {
        this.bodyElement.classList.add('inheritCursors');
        this.bodyElement.style.cursor = 'grabbing';
      }
    
      dragEnd(): void {
        this.bodyElement.classList.remove('inheritCursors');
        this.bodyElement.style.cursor = 'unset';
      }
    
    
    rhenck's avatar
    rhenck committed
      drop(event: CdkDragDrop<DropListComponent>): void {
    
        if (!this.elementModel.readOnly) {
          if (event.previousContainer === event.container) {
    
            moveItemInArray(event.container.data.elementModel.value as string[], event.previousIndex, event.currentIndex);
    
          } else {
            transferArrayItem(
    
              event.previousContainer.data.elementModel.value as string[],
              event.container.data.elementModel.value as string[],
    
              event.previousIndex,
              event.currentIndex
            );
    
            event.previousContainer.data.elementFormControl.setValue(event.previousContainer.data.elementModel.value);
    
          this.elementFormControl.setValue(event.container.data.elementModel.value);
    
    rhenck's avatar
    rhenck committed
        }
      }
    
      onlyOneItemPredicate = (drag: CdkDrag, drop: CdkDropList): boolean => (
    
        !drop.data.elementModel.onlyOneItem || drop.data.elementModel.value.length < 1
    
    rhenck's avatar
    rhenck committed
    }