cdkDragPreview 和 cdkDragPlaceholder 不能按预期使用水平元素
cdkDragPreview and cdkDragPlaceholder not working as expected with horizontal elements
我在我的元素中使用 display-inline,因为我希望它们水平布局,而不是像大多数 Angular 示例中那样垂直布局。也就是说,CSS 的行为很奇怪。我特别有两个问题。
- 当我点击一个元素来拖动它时,它会变大(放下后会缩小回正常大小)。我不确定为什么会发生这种情况,但这绝对不是我们想要的。我已经尝试了很多方法来解决这个问题,通过 css 和添加一个存在 matchSize 的 cdkDragPreview 元素(这似乎是 Angular 推荐的方法)。所有这些努力都失败了。我遇到了以下似乎与我的问题相似的错误报告:https://github.com/angular/components/issues/19060。我注意到该错误已关闭,所以我不知道这是否意味着它已被修复。
- 当我开始从底部下拉列表中拖动一个元素时,当该元素仍在下拉列表中时,其余项目会偶尔移动(当它离开底部下拉列表时,它们的行为与我预期的一样到)。我为 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
我在我的元素中使用 display-inline,因为我希望它们水平布局,而不是像大多数 Angular 示例中那样垂直布局。也就是说,CSS 的行为很奇怪。我特别有两个问题。
- 当我点击一个元素来拖动它时,它会变大(放下后会缩小回正常大小)。我不确定为什么会发生这种情况,但这绝对不是我们想要的。我已经尝试了很多方法来解决这个问题,通过 css 和添加一个存在 matchSize 的 cdkDragPreview 元素(这似乎是 Angular 推荐的方法)。所有这些努力都失败了。我遇到了以下似乎与我的问题相似的错误报告:https://github.com/angular/components/issues/19060。我注意到该错误已关闭,所以我不知道这是否意味着它已被修复。
- 当我开始从底部下拉列表中拖动一个元素时,当该元素仍在下拉列表中时,其余项目会偶尔移动(当它离开底部下拉列表时,它们的行为与我预期的一样到)。我为 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