【问题标题】:CdkDragDrop and ngTemplateOutletCdkDragDrop 和 ngTemplateOutlet
【发布时间】:2019-04-12 03:32:06
【问题描述】:

我正在尝试使用与 Angular Material 7 相关的拖放功能。

我使用 ngTemplateOutlet 将我的模板分成可重复使用的部分,每个选项都可以是 Thing™ 或嵌套的 Thing™,其中包含更多 sub -事物™。

嵌套的事物™ 显示为扩展面板。 我希望所有第一级 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-templates 放回“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™ 的上下文绑定,因为由于共享范围,现在两个模板都有其局部变量引用。

那么,为什么它以第二种方式而不是第一种方式工作呢?

加分项:是否有可能保持第一个代码结构在我看来显然更具可读性和简洁性?

【问题讨论】:

  • 你找到解决方法了吗,面临同样的问题?

标签: angular drag-and-drop angular-material angular7 angular-material-7


【解决方案1】:

我遇到了同样的问题,我什至将其报告为issue on GitHub

原来是cdkDropListcdkDrag分离造成的。 cdkDrag 必须在与cdkDropList 嵌套的标签中,否则被拖动的元素不会检测到放置区域。

在您的情况下,解决方案是在cdkDropList 下方额外添加一个&lt;div cdkDrag&gt;,并且只有在此情况下,您才能使用ngTemplateOutlet 调用模板。

【讨论】:

  • 我怀疑,不幸的是,我必须在两个不同的元素上保持 cdkDrag 分开,所以我会坚持使用不太干净的选项。但感谢您的解释和链接,将此标记为最佳答案
猜你喜欢
  • 2019-10-09
  • 2017-09-20
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 2022-01-06
  • 2019-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多