Angular 8: Как использовать слот Multi-Content-Projection / Multiple-Transclusion дважды? - PullRequest
1 голос
/ 28 марта 2020
  • У меня есть проект Angular 8.2, который имеет два разных режима отображения (альбомная / книжная)
  • И внутри каждого есть панель инструментов вверху и внизу, окружающая основное содержимое.
  • menu, а также основной content - это спецификация модуля c, поэтому я использую слоты. Другими словами: один из 5 возможных родительских компонентов использует этот компонент и предоставляет контент main и (индивидуально разные) menu, используя angular проекция контента .
    <ng-template #menu><ng-content select="[slot='menu']"></ng-content></ng-template>
    <ng-template #content><ng-content select="[slot='content']"></ng-content></ng-template>

    <section *ngIf="landscape">
        <div class="global-ui-top">
            <ng-container *ngTemplateOutlet="menu"></ng-container> // 1st
        </div>
        <some-main-content>
            <ng-container *ngTemplateOutlet="content"></ng-container>
        </some-main-content>
        <div class="global-ui-bottom">
            <ng-container *ngTemplateOutlet="menu"></ng-container> // 2nd
        </div>
    </section>

    // portrait mode
    <section *ngIf="!landscape">
        ... pretty similar to above, also 2× menu, 1× content...

Проблема: Как я могу использовать слот дважды? ** Никакой ошибки не возникает, если я использую, например ..

A <ng-container *ngTemplateOutlet="menu"></ng-container> A
B <ng-container *ngTemplateOutlet="menu"></ng-container> B

... однако слот get только "выбирается один раз "в последний раз (метка между двумя буквами А остается пустой). Другими словами, мой 1-й .global-ui-top остается пустым.

nb: Этот ng-detour в строке 1 + 2 помогает при определенной ошибке . Это не приносит вреда, но и не помогает (к сожалению, ng-template -контенты не замерзают после «первого заполнения»). По-видимому, «принцип выбора» касается слотов.

Есть ли способ вставить содержимое слота меню в шаблон любого вида и использовать повторно это несколько раз (все видно одновременно)? **

  • возможно, причудливый флаг на <ng-content> или <ng-template? ("stati c"?!?)
  • или сначала каким-то образом разбить содержимое слота в @viewChild() (в component.ts) ...
  • else ...?

незначительное обновление

Кажется возможным записать ссылку на шаблон ng в дочерний элемент View:

   @ViewChild('menu', {static: true}) menuA: TemplateRef<any>;

... a console.dir() показывает мне действительный ElementRef, но мне не удается вывести его в шаблоне. html, т.е. <ng-template [ngTemplateOutlet]="menuA"></ng-template>

1 Ответ

1 голос
/ 28 марта 2020

Может быть этот доклад будет полезен.

Насколько я понимаю, ng-content не создает контент, он просто перемещает контент из одной части в другое.

Я думаю, что решение вашей проблемы - использовать ng-template. Например:

projected.component.ts

let instances = 0;

@Component({
  selector: 'app-projected',
template: `projected instance nr: {{ instanceId }}`
})
export class ProjectedComponent implements OnInit {
  instanceId: number;

  constructor() { }

  ngOnInit() {
    this.instanceId = ++instances;
  }

}

parent.component.ts

@Component({
  selector: 'app-parent',
  template: `
    <h3>Parent component</h3>

    <p>Using content #1</p>
    <ng-container *ngTemplateOutlet="content"></ng-container>

    <p>Using content #2</p>
    <ng-container *ngTemplateOutlet="content"></ng-container>
  `,
})
export class ParentComponent implements OnInit {
  @ContentChild('content', { read: TemplateRef }) content: TemplateRef<any>;

  constructor() { }

  ngOnInit() {
  }

}

И вот что важно:

<app-parent>
  <ng-template #content>
    <app-projected></app-projected>
  </ng-template>
</app-parent>

Насколько я понимаю, то, что внутри ng-template, можно рассматривать как проект. Поэтому каждый раз, когда вы используете ng-template, вы создаете новый экземпляр этого чертежа.

Demo

...