CdkDragDrop и ngTemplateOutlet - PullRequest
0 голосов
/ 08 ноября 2018

Я пытаюсь использовать функции перетаскивания, связанные с угловым материалом 7.

Я разделил свой шаблон на куски многократного использования, используя ngTemplateOutlet, и каждая опция может быть либо Вещью ™, либо вложенной Вещью ™, в которой есть некоторые дополнительные элементы . ™.

Вложенные Вещи ™ отображаются в виде панели расширения. Я хочу, чтобы все элементы 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>

Проблема: одиночные Вещи ™ можно перетаскивать, но они не приводятся в исполнение как список, как должен делать cdkDropList, я могу просто перетаскивать их повсюду.

У меня была похожая проблема некоторое время назад, когда попытка использовать выходы шаблонов и возврат ng-template s обратно в «поток 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 ™, потому что теперь оба шаблона имеют ссылку на локальную переменную благодаря общей области действия.

Итак, почему именно он работает вторым способом, а не первым?

Бонусные баллы: возможно ли заставить его работать, сохраняя первую структуру кода, которая, на мой взгляд, кажется более читаемой и чистой?

1 Ответ

0 голосов
/ 12 января 2019

У меня была такая же проблема, я даже сообщал об этом как о проблеме на GitHub .

Оказывается, это вызвано отделением cdkDropList от cdkDrag. cdkDrag должен быть в теге, вложенном в тег с cdkDropList, в противном случае перетаскиваемый элемент не обнаружит зону сброса.

Решением в вашем случае будет дополнительный <div cdkDrag> ниже cdkDropList, и только при этом вы будете вызывать шаблон с ngTemplateOutlet.

...