首页 > 解决方案 > 为什么在使用 Angular Material 时,我拖入下拉列表的元素会丢失顶部和左侧 CSS 属性?

问题描述

在过去的 3 天里,我正在学习 Angular Material Drag And Drop,并尝试使用 Angular Material 将对象/元素拖放到 10x10 矩阵中。

在找到这个 andswer这个 stackblitz之后,我试图将它应用到我的需求和概念中。我必须修复一些错误,更改样式、数组等。

这是我的堆栈闪电战。我非常接近完成它,但是有两个错误我无法弄清楚如何修复它们,并且我在上面的示例中找不到任何解决方案:

  1. 在这个我已经工作了大约 24 小时。将一艘船部署到板上并部署后,当您在板上移动同一艘船时,将其移动到不同的行和列时没有问题。但是当你将它移动到与之前相同的列时,app-ship元素(ShipComponent的选择器)失去了 CSSleft属性。当你将它移动到同一行时,它会失去 CSStop属性,并且在视觉上被放置在矩阵的边缘,与leftprop 一样。拖入同一列的示例: 图片 我完全不知道为什么它会丢失这些属性。

  2. 第二个错误,我还没有处理,但也许你现在会有一些想法,发生在你已经在游戏板上部署了 2 艘或更多艘船时,首先你正在移动一艘船,然后是另一艘,而不是另一艘船将移至第一个,第二个将移至左上角,缺少lefttopCSS 属性。

这两个问题很有可能是相互关联的。

组件.ts:

import { Component, ElementRef, ViewChild } from "@angular/core";
import {
  CdkDragDrop,
  moveItemInArray,
  transferArrayItem,
} from "@angular/cdk/drag-drop";
import { ShipComponent } from "./ship.component";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})

//https://stackblitz.com/edit/angular-salbpl?file=src%2Fapp%2Fapp.component.html
export class AppComponent {
  public list1: Array<ShipComponent>;
  public list2: Array<ShipComponent>;
  public boardP1: number[][];
  public position: any;

  constructor() {
    this.boardP1 = this.getEmptyBoard();
    this.list1 = this.createFleet();
    this.list2 = [];
  }

  @ViewChild("two", { read: ElementRef, static: false }) boardElement: any;
  @ViewChild("ships", { read: ElementRef, static: false }) shipsElement: any;

  onDrop(event: CdkDragDrop<Array<ShipComponent>>) {
    console.clear();
    console.log(this.position);
    event.previousContainer.data[event.previousIndex].top =
      this.position.y -
      this.boardElement.nativeElement.getBoundingClientRect().y;
    event.previousContainer.data[event.previousIndex].left =
      this.position.x -
      this.boardElement.nativeElement.getBoundingClientRect().x;

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

    console.log("t: " + event.container.data[event.previousIndex].top);
    console.log("l: " + event.container.data[event.previousIndex].left);
    console.log("s: " + event.container.data[event.previousIndex].size);
    if (this.shipsElement.nativeElement) {
      console.log("top: " + this.shipsElement.nativeElement.style.top);
      console.log("left: " + this.shipsElement.nativeElement.style.left);
    }
  }

  private createFleet(): Array<ShipComponent> {
    return [
      { size: 4, rotate: false, top: 0, left: 0 },
      { size: 3, rotate: false, top: 0, left: 0 },
      { size: 3, rotate: false, top: 0, left: 0 },
      { size: 2, rotate: false, top: 0, left: 0 },
      { size: 2, rotate: false, top: 0, left: 0 },
      { size: 2, rotate: false, top: 0, left: 0 },
      { size: 1, rotate: false, top: 0, left: 0 },
      { size: 1, rotate: false, top: 0, left: 0 },
      { size: 1, rotate: false, top: 0, left: 0 },
      { size: 1, rotate: false, top: 0, left: 0 },
    ];
  }

  private getEmptyBoard(): number[][] {
    return Array.from({ length: 10 }, () => Array(10).fill(0));
  }
}

组件.html:

<div class="container">
  <div class="ships">
    <h2>Available ships: {{ this.list1.length }}</h2>
    <div
      class="droplist"
      cdkDropList
      #one="cdkDropList"
      [cdkDropListData]="list1"
      [cdkDropListConnectedTo]="[two]"
      (cdkDropListDropped)="onDrop($event)"
      cdkDropListSortingDisabled="true"
    >
      Next:

      <ng-container *ngIf="list1.length > 0">
        <div cdkDrag [style.size]="50 * list1[0].size + 'px'">
          <app-ship [size]="list1[0].size"></app-ship>
        </div>
      </ng-container>
    </div>
  </div>
</div>

<div class="example-boundary">
  <div
    class="droplist"
    cdkDropList
    #two="cdkDropList"
    [cdkDropListData]="list2"
    [cdkDropListConnectedTo]="[one]"
    (cdkDropListDropped)="onDrop($event)"
    cdkDropListSortingDisabled="true"
  >
    <ng-container *ngFor="let ship of list2">
      <app-ship
        #ships
        [size]="ship.size"
        cdkDrag
        [style.top.px]="ship.top"
        [style.left.px]="ship.left"
      >
      </app-ship>
    </ng-container>
    <div class="board">
      <div class="row" *ngFor="let row of boardP1">
        <div class="cell" *ngFor="let box of row" id="columns">
          <button
            #bt
            mat-button
            class="bt-cell"
            (mouseover)="position = bt.getBoundingClientRect()"
          ></button>
        </div>
      </div>
    </div>
  </div>
</div>

标签: javascriptcssangular-materialangular10

解决方案


这个提到的例子可以在线工作,但在我的本地机器上不能正常工作,可能是因为 Angular 8 版本,而我使用的是 10+。我也找不到修复错误的方法。我决定重新构建我的示例项目,并更好地控制我的组件中通过Material Drag and Drop完成的事情。

最后,在工作解决方案中,我决定摆脱CdkDragDrop事件,moveItemInArraytransferArrayItem数组和对象进行手动操作。现在我只使用: cdkDrag, cdkDragStarted, cdkDragEnded,cdkDragMoved事件。

这是我的解决方案的版本,其中修复了提到的错误。


推荐阅读