Угловой 6-кратный нг-контент

Я пытаюсь создать пользовательский компонент, используя несколько NG контента в Angular 6, но это не работает, и я понятия не имею, почему.

Это мой код компонента:

<div class="header-css-class">
<ng-content select="#header"></ng-content>
</div>
 <div class="body-css-class">
<ng-content select="#body"></ng-content>
</div>

Я пытаюсь использовать этот компонент в другом месте и отображать два разных HTML-кода внутри тела и заголовок выбора ng-контента, что-то вроде этого:

<div #header>This should be rendered in header selection of ng-content</div>
<div #body>This should be rendered in body selection of ng-content</div>

Но компонент отображается пустым. Ребята, вы знаете, что я могу делать неправильно или как лучше всего отобразить два разных раздела в одном компоненте?

Спасибо!

6 ответов

Решение

Вы можете добавить фиктивные атрибуты header а также body в отличие от ссылок на шаблоны (#header, #body) и включить с помощью ng-content,

app.comp.html

<app-child>
    <div header >This should be rendered in header selection of ng-content</div>
    <div body >This should be rendered in body selection of ng-content</div>
</app-child>

child.comp.html

<div class="header-css-class">
    <ng-content select="[header]"></ng-content>
</div>
<div class="body-css-class">
    <ng-content select="[body]"></ng-content>
</div>

DEMO

Чтобы соответствовать спецификациям веб-компонентов. Даже если это Angular. Речь идет об избежании атрибутов для селектора, таких как директивы Angular или зарезервированных атрибутов с другим использованием. Итак, мы просто используем атрибут "слот". Посмотрим<ng-content select="[slot=foobar]"> как <slot name="foobar">.

Пример:

hello-world.component.html

<ng-content select="[slot=start]"></ng-content>
<span>Hello World</span>
<ng-content select="[slot=end]"></ng-content>

app.component.html

<app-hello-world>
  <span slot="start">This is a </span>
  <span slot="end"> example.</span>
</app-hello-world>

Результат

This is a Hello World example.

Пример Stackblitz

Вы можете использовать любое имя, например "банан" или "рыба". Но "начало" и "конец" являются хорошим условием для размещения элементов до и после.

В качестве альтернативы вы можете использовать:

app.comp.html

<app-child>
    <div role="header">This should be rendered in header selection of ng-content</div>
    <div role="body">This should be rendered in body selection of ng-content</div>
</app-child>

child.comp.html

<div class="header-css-class">
    <ng-content select="div[role=header]"></ng-content>
</div>
<div class="body-css-class">
    <ng-content select="div[role=body]"></ng-content>
</div>

Дополняя другие ответы:

Вы также можете сделать это с помощью пользовательских тегов (например, <ion-card>, <ion-card-header>, а также <ion-card-content>).

app.comp.html

<app-child>
    <app-child-header>This should be rendered in header selection of ng-content</app-child-header>
    <app-child-content>This should be rendered in content selection of ng-content</app-child-content>
</app-child>

child.comp.html

<div class="header-css-class">
    <ng-content select="app-child-header"></ng-content>
</div>
<div class="content-css-class">
    <ng-content select="app-child-content"></ng-content>
</div>

Вы получите предупреждающее сообщение, но оно будет работать. Вы можете подавить предупреждающие сообщения или использовать известные теги, такие какheader или footer. Однако, если вам не нравится какой-либо из этих методов, вы должны выбрать одно из других решений.

в качестве другого варианта вы можете передавать шаблоны дочернему компоненту, и тогда у вас будет возможность привязать значения к содержимому / шаблонам.

родительский компонент html
      <app-child
    [templateHeader]="header"
    [templateContent]="content>
</app-child>

<ng-template #header
     let-data="data"> < -- how you get dynamic data
     what ever you would like the header to say
     {{data}}
</ng-template>

<ng-template #content>
    what ever you would like the content to say or any other component
</ng-template>
дочерний компонент ts
      export class ChildComponent {
    @Input() templateHeader: TemplateRef<any>;
    @Input() templateContent: TemplateRef<any>;
}
дочерний компонент html
      <div class="header-css-class">
    <ng-container
        *ngTemplateOutlet="
        templateHeader;
        context: {   , < -- if you want to pass data to your template
            data: data
        }">
    </ng-container>
</div>
<div class="content-css-class">
    <ng-container *ngTemplateOutlet="templateContent">
    </ng-container>
</div>

для более полного объяснения шаблонов см. эту замечательную статью https://indepth.dev/posts/1405/ngtemplateoutlet

если вы просто хотите «принять» более одного компонента, вы можете использовать:

      <ng-content select="custom-component,a"></ng-content>

Это принимает элементы пользовательского компонента, а также элементы привязки (а) и не меняет последовательность.

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