Книга: Angular 2 Cookbook
Назад: Attaching behavior to DOM elements with directives
Дальше: Using ngFor and ngIf structural directives for model-based DOM control

Projecting nested content using ngContent

Utilizing components as standalone tags that are self-contained and wholly manage their contents is a clean pattern, but you will frequently find that your component tags demand that they enclose content.

Note

The code, links, and a live example of this are available at .

Getting ready

Suppose you had the following application:

[app/ad-section.component.ts]      import {Component} from '@angular/core';      @Component({     selector: 'ad-section',     template: `       <a href="#">{{adText}}</a>     `   })   export class AdSectionComponent {     adText:string = 'Selfie sticks 40% off!';   }      [app/article.component.ts]      import {Component} from '@angular/core';      @Component({     selector: 'article',     template: `       <h1>{{title}}</h1>       <p>U.S. senators are up in arms following the recent ruling          stripping them of their beloved selfie sticks.</p>       <p>A bipartisan committee drafted a resolution to smuggle          selfie sticks onto the floor by any means necessary.</p>     `   })   export class ArticleComponent {      title:string = 'Selfie Sticks Banned from Senate Floor';   }   

Your objective here is to modify this so that the AdSection component can be incorporated into the Article component without interfering with its content.

How to do it...

The AdSection component wants to incorporate an extra element around the existing Article content. This is easy to accomplish:

[app/article.component.ts]      import {Component} from '@angular/core';      @Component({     selector: 'article',     template: `       <h1>{{title}}</h1>       <ad-section>         <p>U.S. senators are up in arms following the recent ruling            stripping them of their beloved selfie sticks.</p>         <p>A bipartisan committee drafted a resolution to smuggle            selfie sticks onto the floor by any means necessary.</p>       </ad-section>     `   })   export class ArticleComponent {      title:string = 'Selfie Sticks Banned from Senate Floor';   }   

You will notice though that this is a destructive operation. When rendering AdSectionComponent, Angular is not concerned about any content that is inside it. It sees that AdSectionComponent has a template associated with it, and it dutifully supplants the element's contents with it; this template is defined in the @Component decorator. In this case, that wipes out the <p> tags that you want to retain.

To preserve them, you must instruct Angular how it should manage wrapped content. This can be accomplished with an <ng-content> tag:

[app/ad-section.component.ts]      import {Component} from '@angular/core';      @Component({     selector: 'ad-section',     template: `       <a href="#">{{adText}}</a>       <ng-content select="p"></ng-content>     `   })   export class AdSectionComponent {     adText:string = 'Selfie sticks 40% off!';   }   

With this, the ad anchor element is inserted before the wrapped content.

How it works...

Similar to how ng-transclude worked in Angular 1, ng-content serves to interpolate the component tag's wrapped content into its template. The difference here is that ng-content uses a select attribute to target the wrapped elements. This is simply a CSS selector, operating in the same way in which @Component decorators handle the selector property in ComponentMetadata.

There's more...

The select attribute in this example was superfluous, as it ended up selecting the entirety of the wrapped content. Of course, if the select value only matched some of the wrapped content, it would tease out only those elements and interpolate them. <ng-content> will by default insert the entirety of the wrapped content if you decline to provide it with a select value.

Also note that the select attribute is a limited CSS selector. It is not capable of performing complex selections such as :nth-child, and it is only able to target top-level elements inside the wrapping tags. For example, in this application, the paragraph tag inside <div><p>Blah</p></div> would not be included with a select="p" attribute value.

See also

  • Referencing a parent component from a child component describes how a component can gain a direct reference to its parent via injection
  • Configuring mutual parent-child awareness with ViewChild and forwardRef instructs you on how to properly use ViewChild to reference child component object instances
  • Configuring Mutual Parent-Child Awareness with ContentChild and forwardRef instructs you on how to properly use ContentChild to reference child component object instances
Назад: Attaching behavior to DOM elements with directives
Дальше: Using ngFor and ngIf structural directives for model-based DOM control

thank you
Flame
cant read the code since it is all on a single line. Also this comments section is russian
Rakuneque
DATA COLLECTION AND ANALYSIS Two reviewers extracted data and assessed methodological quality independently lasix torsemide conversion Many others were in that space already