I recently came across some interesting behavior with Angular's
ng-content that I wanted to jot down so I can search for some answers. NgContent isn't well documented.
ng-content is to be used like any other element. This is great, especially for rendering in default content. For example, a component that can transclude some content but if for some reason nothing is nested into it, it will show a default state.
<profile-card> <ng-content> <img src="/defaultProfile.jpg"/> <p>Unknown</p> </ng-content> </profile-card>
But what if you don't need anything within the opening and closing tags? You'd think that just
<ng-content /> would be a nice and simple way to signal where to place the included content, but attempting to do so generates the following error:
Template parse errors: Only void and foreign elements can be self closed "ng-content" [ERROR ->]<ng-content />
Seems weird to me. This may be by design.
One of the features of
ng-content is that you can use the
select attribute on it to pull transcluded content into a specific location.
<!-- my-component.html --> <div> <ng-content select=".title"></ng-content> <ng-content select=".subtitle"></ng-content> </div>
This is great for enforcing layout in a specific way. Except... it has a major caveat, at least in my opinion. This select only seems to match immediate children only, nothing else.
So using the above
my-component, this belwo works while placing the
title above the
<my-component> <p class="subtitle">world</p> <h2 class="title">Hello</h2> </my-component>
but then this doesn't! Nothing is rendered.
<my-component> <div> <h2 class="title">Hello</h2> <p class="subtitle">world</p> </div> </my-component>
It can't find these same elements because they're wrapped in an extra div? I would have thought that it would match those elements as well, just like
querySelector or CSS selectors would. If I only wanted immediate children I would have used something like
select="> .title". My assumption that it used standard selectors is wrong? ¯\(ツ)/¯ That sucks.