1

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

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

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

4

1 回答 1

2

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

你可以在这个 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>

我使用一个返回数组或单词的 observable。在subscribeI 等于 item 并使用 asetTimeout()将大小添加到外部 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]。为此,您有两个数组:单词和项目

如果 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

查看新的堆栈闪电战

于 2020-05-31T19:59:00.050 回答