如何将 Angular Material 拖放与 Flex 布局结合使用?

How can I use Angular Material Drag n Drop with Flex Layout?

我正在尝试制作一个具有拖放功能和响应能力的网格。首先我尝试使用 grid list 但我找不到如何让它响应不同的屏幕尺寸。

我放弃了网格列表,我决定使用 angular flex layout library to create my own grid that would be inherently responsive. Then I tried combining that with Angular Material Drag n Drop 但它没有正常工作。

具体来说,我可以在网格元素周围拖动,但这种行为充其量是不稳定的。有时我可以重新排序元素,有时不能。有时我向左移动一个元素,它向右移动,有时则相反。你明白了。这是不可预测的。另一个问题是,如果您四处拖动元素,网格中的其他随机元素会出现和消失。

我尝试阅读拖放文档,但我开始觉得它不应该按照我想要的方式工作。有谁知道可能适合我的实现方式吗?

这是我的代码:

我的-component.html

<div fxFlex fxLayout="column" fxLayoutGap="1%">
  <div fxLayout="row wrap" fxLayoutGap="16px grid"
       cdkDropList
       [cdkDropListData]="numbers"
       (cdkDropListDropped)="drop($event)">

    <div *ngFor="let n of numbers"
         fxFlex="25%"
         fxFlex.md="33%"
         fxFlex.sm="50%"
         fxFlex.xs="100%"
         cdkDrag>
      <div fxLayout="row" style="width: 200px; height: 200px; background-color: red;">
        Number: {{n}}
      </div>
    </div>

</div>

我的-component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { CdkDragDrop, CdkDropList, CdkDropListGroup, moveItemInArray } from "@angular/cdk/drag-drop";

@Component({
  selector: 'app-menu',
  templateUrl: './my-component.html',
  styleUrls: ['./my-component.scss']
})
export class MyComponent implements OnInit {
  @ViewChild(CdkDropListGroup) listGroup!: CdkDropListGroup<CdkDropList>;
  @ViewChild(CdkDropList) placeholder!: CdkDropList;

  numbers = [1, 2, 3, 4, 5, 6, 7, 8];

  constructor() {
  }

  ngOnInit(): void {
  }

  drop(event: CdkDragDrop<number[]>) {
    console.log("drop() prev index: " + event.previousIndex + ", cur index: " + event.currentIndex);
    moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
  }
}

我很努力地尝试将 @angular/flex-layout@angular/cdk/drag-drop 结合起来,但是问题太多了。所以我用 css flex 做了 而且反应灵敏。

angular-drag-drop-flex-wrap

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

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
  drop(event: CdkDragDrop<any>) {
    this.items[event.previousContainer.data.index] = event.container.data.item;
    this.items[event.container.data.index] = event.previousContainer.data.item;
  }
}
.categories {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap; /* NEW */
  width: 100%;
}

.inner {
  width: 100%;
  height: 100%;
  border: 1px solid blue;
  text-align: center;
  line-height: 5rem;
  background-color: #efefef;
  cursor: move;
}

.categories-item {
  flex: 1 0 5rem; /* NEW */
  margin: 5px; /* NEW */
  background-color: transparent;
  height: 5rem;
  text-align: center;
  line-height: 5rem;
  position: relative;
}
.placeholder {
  flex: 1 0 5rem; /* NEW */
  margin: 5px; /* NEW */
  background-color: white;
  height: 5rem;
  text-align: center;
  line-height: 5rem;
  border: 1px;
}
.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
<div #contenedor class="categories" cdkDropListGroup>
    <ng-container *ngFor="let item of items;let i=index">
        <div class="categories-item" cdkDropList  cdkDropListOrientation="horizontal"
            [cdkDropListData]="{item:item,index:i}" (cdkDropListDropped)="drop($event)">
            <div class="inner" cdkDrag>
                <div class="example-custom-placeholder" *cdkDragPlaceholder></div>
                {{item}}
            </div>
        </div>
    </ng-container>
</div>
{{items|json}}