I've seen working examples when <ng-content>
is beeing used inside other nested components (like here) but I haven't managed to run it inside a root Angular2 component:
HTML template:
<html> <body> <app> <h1>Hello, World!</h1> </app> </body> </html>
Angular 2 component in TypeScript:
import {Component, View, bootstrap} from 'angular2/angular2'; @Component({ selector: 'app' }) @View({ template: 'Header: <ng-content></ng-content>', }) export class App { } bootstrap(App);
I'd expect that this will generate:
<app> Header: <h1>Hello, World!</h1> </app>
but it doesn't and the content of <app>
is ignored. See demo on Plunker.
I thought maybe this goes against some Angular 2 philosophy or something so it's not even supported, but my use case is very similar to the first working demo I think.
What is ng-content The ng-content tag acts as a placeholder for inserting external or dynamic content. The Parent component passes the external content to the child component. When Angular parses the template, it inserts the external content where ng-content
They are used to create configurable components. This means the components can be configured depending on the needs of its user. This is well known as Content Projection. Components that are used in published libraries make use of <ng-content> to make themselves configurable. Consider a simple <project-content> component:
In the template for your component, add an <ng-content> element where you want the projected content to appear. Add a select attribute to the <ng-content> elements. Angular supports selectors for any combination of tag name, attribute, CSS class, and the :not pseudo-class.
It renders the content as is. At the maximum you can split the content and render them at different locations of your view with the help of select attribute. You cannot conditionally render the content within ng-content. You have to show the content that is received from the parent with no means to make decisions based on the content.
When you run your example, did you notice how Hello World!
is displayed during loading?
Basically, the HTML between <app>
and </app>
is used to display something while Angular is booting up.
Also, from the source:
An application is bootstrapped inside an existing browser DOM, typically
index.html
. Unlike Angular 1, Angular 2 does not compile/process bindings inindex.html
. This is mainly for security reasons, as well as architectural changes in Angular 2. This means thatindex.html
can safely be processed using server-side technologies such as bindings. Bindings can thus use double-curly{{ syntax }}
without collision from Angular 2 component double-curly{{ syntax }}
.
The important part being Angular 2 does not compile/process bindings in index.html
. So, in order to do what you want, you will have to move ng-content
to a child component.
Turns out it's possible, if you intend to provide textual content. If you want Angular components, it's possible with the right HTML element (noscript). A little hacky, one might say. The trick is using a <noscript>
element.
HTML template:
<noscript id="appContent"> <h1>Hello, World!</h1> <a [routerLink]="['Home']">Home</a> </noscript> <script> var mainTemplate = document.getElementById('appContent'); window.mainTemplate = mainTemplate.innerText; </script>
Root component:
import {Component, bootstrap} from 'angular2/angular2'; @Component({ selector: 'app', template: 'Header: ' + window.mainTemplate , }) export class App { } bootstrap(App);
Make sure your Angular 2 code comes after the template definition.
Only applies if you use a <template>
tag: The catch is that since recently (http://angularjs.blogspot.com.br/2016/02/angular-2-templates-will-it-parse.html) Angular 2 brings its own parser, templates are case-sensitive. It is not the case for HTML in a browser environment. It means the browser may not keep the case in attributes and elements on this template hack.
UPDATE: I had a <template>
element in the original solution. A <noscript>
is much better as shouldn't be any case conversion.
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