Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Component with <ng-content>

Tags:

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.

like image 796
martin Avatar asked Sep 14 '15 15:09

martin


People also ask

What is the use of ng content in angular?

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

What is the use of <ng-content> components?

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:

How do I project content to a component in angular?

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.

How to conditionally render the content in ng-content?

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.


Video Answer


2 Answers

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 in index.html. This is mainly for security reasons, as well as architectural changes in Angular 2. This means that index.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.

like image 161
Jesse Good Avatar answered Sep 28 '22 00:09

Jesse Good


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.

like image 34
André Werlang Avatar answered Sep 27 '22 22:09

André Werlang