Wiele treści ng

104

Próbuję zbudować niestandardowy komponent przy użyciu wielu ng-contentw Angular 6, ale to nie działa i nie mam pojęcia, dlaczego.

To jest mój kod komponentu:

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

Próbuję użyć tego składnika w innym miejscu i renderowanie dwa różne wewnątrz kodu HTML bodyi nagłówek selecto ng-content, coś takiego:

<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>

Ale komponent jest renderowany jako pusty.

Czy wiecie, co mogę zrobić źle lub jaki jest najlepszy sposób renderowania dwóch różnych sekcji w tym samym komponencie?

Dzięki!

Lucas Santos
źródło
Przepraszamy, stackoverflow nie zapisał mojego drugiego fragmentu kodu: Kod, którego używam w komponencie, wygląda mniej więcej tak: <div #header> To jest treść nagłówka </div> <div #body> To jest treść </div>
Lucas Santos

Odpowiedzi:

194
  1. Możesz dodać atrybuty fikcyjne headeri bodyzamiast odwołań do szablonów (#header, #body).
  2. I transkluduj użycie ng-contentz selectatrybutem takim jak select="[header]".

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>

PRÓBNY

Amit Chigadani
źródło
7
Jeśli nie chcesz renderować dodatkowego div lub innego znacznika, użyj <ng-container>
sobczi
3
@AmitChigadani wierzę @sobczi oznaczało, że można zastąpić <div header>z <ng-container header>.
user12893298320392
4
Potwierdzam, zastępując <div header>przy <ng-container header>pracach zbyt.
azerafati
51

Aby dopasować się do specyfikacji składnika sieci Web . Nawet jeśli to jest Angular. Chodzi o unikanie atrybutów selektora, takich jak dyrektywy Angular lub zarezerwowane atrybuty z innym użyciem. Dlatego po prostu używamy atrybutu „slot”. Zobaczymy <ng-content select="[slot=foobar]">jako <slot name="foobar">.

Przykład:

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>

Wynik

This is a Hello World example.

Przykład Stackblitz

Możesz użyć dowolnej nazwy, np. „Banan” lub „ryba”. Ale „początek” i „koniec” to dobra konwencja umieszczania elementów przed i po.

Dominik
źródło
Jak mogę odpytać te elementy? z miejscem na nazwisko.
Nexeuz
To zależy od ustawień kątowych i komponentów oraz od tego, czego dokładnie chcesz. Możesz używać ViewChild w TS lub :hostiw ::ng-deepSCSS. Ale to tylko przykład. Zobacz Stackblitz Może ::slotted/ ::contentbędzie również działać. Ale, nie pewne. W sieci znajdziesz więcej informacji na ten temat. Ogólnie rzecz biorąc, należy stylizować tylko sam komponent. I unikaj stylizacji na zewnątrz (globalnie). W przeciwnym razie będziesz mieć niepożądane skutki uboczne.
Dominik
Dobrą praktyką jest zawijanie go. Zobacz zaktualizowany przykład Stackblitz w moim ostatnim komentarzu. Zobacz plik html i css komponentu. Powinieneś preferować to od ng-deep. Np. <div class="end"><ng-content></ng-content></div>Ponieważ ten element jest dostępny w komponencie. Zawartość ng jest tylko pseudoelementem, który jest zastępowany przez zadokowany element na zewnątrz. Musisz więc użyć selektora ng-deep.
Dominik
9

alternatywnie możesz użyć:

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>
Angelo Radici
źródło
4

Uzupełniając inne odpowiedzi:

Można również zrobić to z niestandardowych znaczników (jak <ion-card>, <ion-card-header>i <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>

Otrzymasz komunikat ostrzegawczy, ale zadziała. Możesz pominąć komunikaty ostrzegawcze lub użyć znanych znaczników, takich jak headerlub footer. Jeśli jednak nie podoba ci się żadna z tych metod, powinieneś wybrać jedno z pozostałych rozwiązań.

Wesley Gonçalves
źródło