cdkDragPreview 和 cdkDragPlaceholder 不能按预期使用水平元素

cdkDragPreview and cdkDragPlaceholder not working as expected with horizontal elements

我在我的元素中使用 display-inline,因为我希望它们水平布局,而不是像大多数 Angular 示例中那样垂直布局。也就是说,CSS 的行为很奇怪。我特别有两个问题。

  1. 当我点击一个元素来拖动它时,它会变大(放下后会缩小回正常大小)。我不确定为什么会发生这种情况,但这绝对不是我们想要的。我已经尝试了很多方法来解决这个问题,通过 css 和添加一个存在 matchSize 的 cdkDragPreview 元素(这似乎是 Angular 推荐的方法)。所有这些努力都失败了。我遇到了以下似乎与我的问题相似的错误报告:https://github.com/angular/components/issues/19060。我注意到该错误已关闭,所以我不知道这是否意味着它已被修复。
  2. 当我开始从底部下拉列表中拖动一个元素时,当该元素仍在下拉列表中时,其余项目会偶尔移动(当它离开底部下拉列表时,它们的行为与我预期的一样到)。我为 cdkDragPlaceholder 创建了一个隐藏样式,因为这似乎是 Angular 提供对此的控制的方式,但它只对顶部下拉列表有帮助,似乎对底部没有影响。

这里有一个 link 说明了 StackBlitz 上的两个问题:https://stackblitz.com/edit/spuzzler。我猜我的问题可以用 CSS 解决,但我不知道如何解决。

为每个单词创建一个cdkDropList。我的想法是有一个外部 div 和一个内部 div ,它们实际上是被拖动的元素。此外,我固定了外部 div 的大小。因此,当您拖动时,单词不会重新排序(只是留下一个空的 space 而不是您拖动的单词)

你可以在this stackblitz

中看到结果
<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 *cdkDragPlaceholder></div>
        <div class="categories-item-drag" *cdkDragPreview matchSize="true" >
          <div class="inner">{{item}}</div>
        </div>
        {{item}}
        </div>
        </div>
    </ng-container>
</div>

我使用一个 returns 数组或单词的可观察对象。在 subscribe 中,我等于项目,并使用 setTimeout() 将尺寸添加到外部 div

export class AppComponent implements OnInit {
  @ViewChildren(CdkDropList, { read: ElementRef }) pills: QueryList<ElementRef>;
  constructor(private renderer: Renderer2) {}
  items: any[];
  positions: any[];
  ngOnInit() {
    this.getParragraf().subscribe(res => {
      this.items = res;
      setTimeout(() => {
        this.pills.forEach(x => {
          this.renderer.setStyle(
            x.nativeElement,
            "width",
            x.nativeElement.getBoundingClientRect().width + "px"
          );
        });
      });
    });
  }

  drop(event: CdkDragDrop<any>) {
    this.items.splice(event.previousContainer.data.index, 1);
    this.items.splice(event.container.data.index,0,event.previousContainer.data.item)
    /* if we want to interchange the words, replace the two lines by*/
    //this.items[event.previousContainer.data.index]=event.container.data.item
    //this.items[event.container.data.index]=event.previousContainer.data.item
    //event.currentIndex=0;
    

  }

  getParragraf() {
    return of(
      "Let him who walks in the dark, who has no light, trust in the name of the Lord and rely on his God.".split(
        " "
      )
    );
  }
}

已更新 其实你不需要做一个cdkDropListGroup,你可以利用[cdkDropListConnectedTo]。为此,您有两个数组:words 和 items

如果 res 是一个字符串数组,你可以

  this.items = res.map((x,index)=>({value:x,ok:false,id:'id'+index}));
  this.words=res.map(x=>({o:Math.random(),value:x}))
             .sort((a,b)=>a.o-b.o)
             .map(x=>(
               {value:x.value,
               connected:this.items.filter(w=>x.value==w.value).map(x=>x.id)
               }))

并使用item.value、item.id和word.value、word.connected

看到一个new stackblitz