CdkDragDrop 和 ngTemplateOutlet
CdkDragDrop and ngTemplateOutlet
我正在尝试使用与 Angular Material 7.
相关的拖放功能
我使用 ngTemplateOutlet
将模板分成可重复使用的部分,每个选项都可以是 Thing™ 或嵌套的 Thing™ 有更多 子事物 ™。
嵌套的 Things™ 显示为扩展面板。
我希望所有一级 Things™ 都可以像列表一样重新排序。
(好吧好吧,很明显这是一个带有普通和嵌套选项的可重新排序的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>
问题:单个 Things™ 是可拖动的,但它们不像 cdkDropList 应该做的那样被强制执行,我可以将它们到处拖动。
前段时间我在尝试使用模板插座并将 ng-template
s 放回 'HTML flow' 工作时遇到了类似的问题,所以我尝试了同样的方法。
<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™ 的上下文绑定,因为现在两个模板都有其由于共享范围,局部变量引用。
那么,为什么它以第二种方式而不是第一种方式起作用呢?
奖励积分:是否有可能让它在保持第一个代码结构的情况下工作,在我看来,它显然更具可读性和简洁性?
我遇到了同样的问题,我什至将其报告为 issue on GitHub。
原来是cdkDropList
和cdkDrag
分开造成的。 cdkDrag
必须位于嵌套在带有 cdkDropList
的标签内,否则被拖动的元素将无法检测到拖放区。
您的解决方案是在 cdkDropList
下方添加一个 <div cdkDrag>
,并且只有在此之下您才能使用 ngTemplateOutlet
.
调用模板
我正在尝试使用与 Angular Material 7.
相关的拖放功能我使用 ngTemplateOutlet
将模板分成可重复使用的部分,每个选项都可以是 Thing™ 或嵌套的 Thing™ 有更多 子事物 ™。
嵌套的 Things™ 显示为扩展面板。 我希望所有一级 Things™ 都可以像列表一样重新排序。
(好吧好吧,很明显这是一个带有普通和嵌套选项的可重新排序的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>
问题:单个 Things™ 是可拖动的,但它们不像 cdkDropList 应该做的那样被强制执行,我可以将它们到处拖动。
前段时间我在尝试使用模板插座并将 ng-template
s 放回 'HTML flow' 工作时遇到了类似的问题,所以我尝试了同样的方法。
<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™ 的上下文绑定,因为现在两个模板都有其由于共享范围,局部变量引用。
那么,为什么它以第二种方式而不是第一种方式起作用呢?
奖励积分:是否有可能让它在保持第一个代码结构的情况下工作,在我看来,它显然更具可读性和简洁性?
我遇到了同样的问题,我什至将其报告为 issue on GitHub。
原来是cdkDropList
和cdkDrag
分开造成的。 cdkDrag
必须位于嵌套在带有 cdkDropList
的标签内,否则被拖动的元素将无法检测到拖放区。
您的解决方案是在 cdkDropList
下方添加一个 <div cdkDrag>
,并且只有在此之下您才能使用 ngTemplateOutlet
.