我正在尝试使用与Angular Material 7关联的拖放功能。
我使用ngTemplateOutlet
将模板分成可重复使用的部分,每个选项可以是 Thing ™或嵌套的 Thing ™,其中还包含一些 sub-Things ™。
嵌套的事物™显示为扩展面板。 我希望所有第一级的事物™都可以重新排序,就好像thery是一个列表一样。
(好吧,很明显,这是具有常规选项和嵌套选项的可重新排序的sidenav,只是假装它不太明显)
这是我最初编写的代码。
<div cdkDropList (cdkDropListDropped)="dropItem($event)" lockAxis="y">
<ng-container *ngFor="let thing of things">
<ng-container
*ngTemplateOutlet="!thing.children ? singleThing : multipleThing; context: { $implicit: thing }"
></ng-container>
</ng-container>
</div>
<ng-template #singleThing let-thing>
<div cdkDrag>
<ng-container *ngTemplateOutlet="thingTemplate; context: { $implicit: thing }"></ng-container>
</div>
</ng-template>
<ng-template #multipleOption let-thing>
<mat-expansion-panel cdkDrag (cdkDropListDropped)="dropItem($event)">
<mat-expansion-panel-header>
<mat-panel-title>
<p>Nested thing title</p>
<span cdkDragHandle></span>
</mat-panel-title>
</mat-expansion-panel-header>
<ng-container *ngFor="let childThing of thing.children">
<div class="childThing">
<ng-container *ngTemplateOutlet="thingTemplate; context: { $implicit: childThing }"></ng-container>
</div>
</ng-container>
</mat-expansion-panel>
</ng-template>
<ng-template #thingTemplate let-thing>
<p>I'm a thing!</p>
<span cdkDragHandle></span>
</ng-template>
问题:单个事物™是可拖动的,但没有像cdkDropList应该做的那样强制执行,我可以将它们拖到任何地方。
前段时间,当我尝试使用模板出口并将ng-template
放回“ HTML流”中时也遇到了类似的问题,因此我尝试了相同的问题。
<div cdkDropList (cdkDropListDropped)="dropItem($event)" lockAxis="y">
<ng-container *ngFor="let thing of things">
<ng-container
*ngIf="!thing.children; then singleThing; else multipleThing"
></ng-container>
<ng-template #singleThing>
<div cdkDrag>
<ng-container *ngTemplateOutlet="thingTemplate; context: { $implicit: thing }"></ng-container>
</div>
</ng-template>
<ng-template #multipleOption>
<mat-expansion-panel cdkDrag (cdkDropListDropped)="dropItem($event)">
<mat-expansion-panel-header>
<mat-panel-title>
<p>Nested thing title</p>
<span cdkDragHandle></span>
</mat-panel-title>
</mat-expansion-panel-header>
<ng-container *ngFor="let childThing of thing.children">
<div class="childThing">
<ng-container *ngTemplateOutlet="thingTemplate; context: { $implicit: childThing }"></ng-container>
</div>
</ng-container>
</mat-expansion-panel>
</ng-template>
</ng-container>
</div>
<ng-template #thingTemplate let-thing>
<p>I'm a thing!</p>
<span cdkDragHandle></span>
</ng-template>
当然,为什么不起作用呢! 是的,很好,但是为什么?
变化不大,我们使用了ngIf
而不是第一个ngTemplateOutlet
,并删除了 Thing ™的上下文绑定,因为现在两个模板都具有其局部变量引用,这要归功于共享范围。
那么,为什么它确实能以第二种方式而不是第一种方式起作用?
要点:在我看来,第一个代码结构显然更具可读性和简洁性吗?
答案 0 :(得分:0)
我遇到了同样的问题,甚至报告为issue on GitHub。
事实证明是由于cdkDropList
与cdkDrag
的分离所致。 cdkDrag
必须位于与cdkDropList
一起嵌套的标记中,否则拖动的元素将无法检测到放置区域。
您遇到的解决方案是在<div cdkDrag>
下方添加一个cdkDropList
,只有在此之下,您才能使用ngTemplateOutlet
来调用模板。