angular - CdkDragDrop 和 ngTemplateOutlet

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

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

我使用 ngTemplateOutlet 将模板分成可重复使用的部分每个选项都可以是 东西 ™ 或嵌套的 东西 ™ 还有更多子事物 ™。

嵌套 事情 ™ 显示为扩展面板。
我要全部一级事情 ™ 可以像列表一样重新排序。

(好吧,好吧,很明显这是一个带有正常和嵌套选项的可重新排序的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 那样强制执行,我可以将它们拖到任何地方。

前段时间我在尝试使用模板 socket 并放置 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并删除了 的上下文绑定(bind)东西 ™ 因为现在两个模板都具有其局部变量引用,这要归功于共享范围。

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

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

最佳答案

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

原来是cdkDropList的分离造成的来自 cdkDrag . cdkDrag必须在一个标签中,该标签嵌套在带有 cdkDropList 的标签中,否则被拖动的元素不会检测到放置区。

在您的情况下,解决方案将是一个额外的 <div cdkDrag>下面cdkDropList ,并且只有在此之下,您才能使用 ngTemplateOutlet 调用模板.

关于angular - CdkDragDrop 和 ngTemplateOutlet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53210886/

相关文章:

javascript - Angular Material 选项卡标题不需要的行为

Angular:如果 MatMenu 没有 MatMenuItem,则禁用 MatButton

javascript - 如何使用 Angular 8 切换行

javascript - Angular 6 Validators.pattern() 正则表达式不起作用

javascript - 我将如何将拖放项目保存到表单变量并通过电子邮件发送?

python - 如何在wxpython框架中拖动图像

java - 如何以编程方式取消 Java/Swing 中的拖放操作?

javascript - 可观察与回调

html - Angular 最佳实践 : for reusability, 制作新的 CSS 类或新组件?

angular - 在 Angular 中包装 html 标签绑定(bind)的 UI 组件