CdkDragDrop и ngTemplateOutlet

Я пытаюсь использовать функции Drag&Drop, связанные с Angular Material 7.

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

Nested 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Вернувшись к "потоку 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 ответов

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

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

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

Другие вопросы по тегам