To add multiple ng-content, we need to add the select attribute as shown below. The select attribute property creates a mapping between the templates where these need to be transcluded.
The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.
Known limitations of our implementation are as follows: You cannot data-bind the slot's name attribute. You cannot data-bind the slot attribute. You cannot dynamically generate slot elements inside a component's view.
Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.
header
and body
as opposed to template references (#header, #body)
.ng-content
with select
attribute like 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>
DEMO
To fit the Web Component specs. Even if that's Angular. It's about avoiding attributes for selector like Angular directives or reserved attributes with another use. So, we just use the "slot" attribute. We'll see <ng-content select="[slot=foobar]">
as <slot name="foobar">
.
Example:
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>
Result
This is a Hello World example.
You can use any name you want like "banana" or "fish". But "start" and "end" are a good convention to place elements before and after.
alternatively you can use:
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>
Complementing the other answers:
You can also do it with custom tags (like <ion-card>
, <ion-card-header>
, and <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>
You'll get a warning message, but it will work.
You can suppress the warning messages or use known tags such as header
or footer
.
However, if you don't like any of these methods, you should go with one of the other solutions.
as another option you can pass templates to the child component, and then you would have the benefit of being able to bind values to the content / templates
<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>
export class ChildComponent {
@Input() templateHeader: TemplateRef<any>;
@Input() templateContent: TemplateRef<any>;
}
<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>
for a more complete explanations of templates see this great article https://indepth.dev/posts/1405/ngtemplateoutlet
if you just want to "accept" more than one component, you can use:
<ng-content select="custom-component,a"></ng-content>
This accepts elements of custom-component as well as anchor (a) elements and does not change the sequence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With