ANGULAR
Complete Angular Tutorial For Beginners Introduction to Angular | What is Angular? Architecture Overview & Concepts of Angular How to Install Angular How to Create a new project in Angular Bootstrapping in Angular: How It Works Internally Angular Components Overview & Examples Data Binding in Angular Interpolation in Angular Property Binding in Angular Event Binding in Angular ngModel & Two way Data binding in Angular NgModelChange & Change Event in Angular Child/Nested Components in Angular angular directives angular ngFor directive ngSwitch, ngSwitchcase, ngSwitchDefa ult Angular Example How to use ngIf, else, then in Angular By example NgClass Example Conditionally apply class Angular ngStyle Directive Angular Trackby to improve ngFor Performance How to Create & Use Custom Directive In Angular Working with Angular Pipes How to Create Custom Pipe in Angular Formatting Dates with Angular Date Pipe Using Angular Async Pipe with ngIf & ngFor angular keyValue pipe Using Angular Pipes in Components or Services Angular Component Communication & Sharing Data Angular Pass data to child component Angular Pass data from Child to parent component Component Life Cycle Hooks in Angular Angular ngOnInit And ngOnDestroy Life Cycle hook Angular ngOnChanges life Cycle Hook Angular ngDoCheck Life Cycle Hook Angular Forms Tutorial: Fundamentals & Concep t s Angular Template-driven forms example How to set value in template-driven forms in Angular Angular Reactive Forms Example Using Angular FormBuilder to build Forms SetValue & PatchValue in Angular StatusChanges in Angular Forms ValueChanges in Angular Forms FormControl in Angular FormGroup in Angular Angular FormArray Example Nested FormArray Example Add Form Fields Dynamically SetValue & PatchValue in FormArray Angular Select Options Example in Angular Introduction to Angular Services Introduction to Angular Dependency Injection Angular Injector, @Injectable & @Inject Angular Providers: useClass, useValue, useFactory & useExisting Injection Token in Angular How Dependency Injection & Resolution Works in Angular Angular Singleton Service ProvidedIn root, any & platform in Angular @Self, @SkipSelf & @Optional Decorators Angular '@Host Decorator in Angular ViewProviders in Angular Angular Reactive Forms Validation Custom Validator in Angular Reactive Form Custom Validator with Parameters in Angular Inject Service Into Validator in Angular template_driven_form_validation_in_angular Custom Validator in Template Driven Forms in Angular Angular Async Validator Example Cross Field or Multi Field Validation Angular How to add Validators Dynamically using SetValidators in Angular Angular HttpClient Tutorial & Example Angular HTTP GET Example using httpclient Angular HTTP POST Example URL Parameters, Query Parameters, httpparams in Angular HttpClient Angular HTTPHeaders Example Understanding HTTP Interceptors in Angular Angular Routing Tutorial with Example Location Strategy in Angular Angular Route Params Angular : Child Routes / Nested Route Query Parameters in Angular Angular Pass Data to Route: Dynamic/Static RouterLink, Navigate & NavigateByUrl to Navigate Routes RouterLinkActive in Angular Angular Router Events ActivatedRoute in Angular Angular Guards Tutorial Angular CanActivate Guard Example Angular CanActivateChild Example Angular CanDeactivate Guard Angular Resolve Guard Introduction to Angular Modules or ngModule Angular Routing between modules Angular Folder Structure Best Practices Guide to Lazy loading in Angular Angular Preloading Strategy Angular CanLoad Guard Example Ng-Content & Content Projection in Angular Angular @input, @output & EventEmitter Template Reference Variable in Angular ng-container in Angular How to use ng-template & TemplateRef in Angular How to Use ngTemplateOutlet in Angular '@Hostbinding and @Hostlistener_in_Angular Understanding ViewChild, ViewChildren &erylist in Angular ElementRef in Angular Renderer2 Example: Manipulating DOM in Angular ContentChild and ContentChildren in Angular AfterViewInit, AfterViewChecked, AfterContentInit & AfterContentChecked in Angular Angular Decorators Observable in Angular using RxJs Create observable from a string, array & object in angular Create Observable from Event using FromEvent in Angular Using Angular observable pipe with example Angular Map Operator: Usage and Examples Filter Operator in Angular Observable Tap operator in Angular observable Using SwitchMap in Angular Using MergeMap in Angular Using concatMap in Angular Using ExhaustMap in Angular Take, TakeUntil, TakeWhile & TakeLast in Angular Observable First, Last & Single Operator in Angular Observable Skip, SkipUntil, SkipWhile & SkipLast Operators in Angular The Scan & Reduce operators in Angular DebounceTime & Debounce in Angular Delay & DelayWhen in Angular Using ThrowError in Angular Observable Using Catcherror Operator in Angular Observable ReTryWhen inReTry, ReTryWhen in Angular Observable Unsubscribing from an Observable in Angular Subjects in Angular ReplaySubject, BehaviorSubject & AsyncSubject in Angular Angular Observable Subject Example Sharing Data Between Components Angular Global CSS styles View Encapsulation in Angular Style binding in Angular Class Binding in Angular Angular Component Styles How to Install & Use Angular FontAwesome How to Add Bootstrap to Angular Angular Location Service: go/back/forward Angular How to use APP_INITIALIZER Angular Runtime Configuration Angular Environment Variables Error Handling in Angular Applications Angular HTTP Error Handling Angular CLI tutorial ng new in Angular CLI How to update Angular to latest version Migrate to Standalone Components in Angular Create Multiple Angular Apps in One Project Set Page Title Using Title Service Angular Example Dynamic Page Title based on Route in Angular Meta service in Angular. Add/Update Meta Tags Example Dynamic Meta Tags in Angular Angular Canonical URL Lazy Load Images in Angular Server Side Rendering Using Angular Universal The requested URL was not found on this server error in Angular Angular Examples & Sample Projects Best Resources to Learn Angular Best Angular Books in 2020

Ng-Content & Content Projection in Angular

In this guide let us explore how to use ng-content to add external content (content projection) in the Template. We know how to use @Input decorator to pass data from the parent component to the child component. But it is only limited to data. We cannot use that technique to pass the content which includes the HTML elements, CSS, etc to the child component. To do that we have to make use of content projection.

Content projection is a way to pass the HTML content from the parent component to the child component. The child component will display the template in a designated spot. We use the ng-content element to designate a spot in the template of the child component. The ng-content also allows us to create multiple slots using the selector attribute. The parent can send different content to each slot.

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 appears in the child component’s template

We can use content projection to create a reusable component. The components that have similar logic & layout and can be used in many places in the application.

Take an example of a card component. It has a header section,footer section & body section. The contents of these sections will vary. The ng-content will allow us to pass these sections to the card component from the parent component. This enables us to use the card component at many places in the app.

Without ng-content

To understand how content projection using ng-content works, first let us build a simple button component without ng-content.

Create a new Angular application. Add a new component btn.component.ts.It is a simple component, which displays a button with the caption Click Me

                              

import { Component } from '@angular/core';
 
@Component({
 selector: 'app-btn',
 template: `<button>
       Click Me
     </button>`
})
export class BtnComponent {
}
 
                            
                        

Now go to the app.component.html.

                              

<h2>Simple Button Demo</h2>
<app-btn></app-btn>
<app-btn></app-btn>
 
                            
                        

In the code above, we have two buttons with the caption Click Me show up on the screen as expected.

What if we want to change the caption from the parent. We can do that using the @Input property. But using @input, we can only set the caption of the button. But we cannot change the look and appearance of the caption.

ng-content Example

Create a new component FancyBtnComponent. Copy all the codes from BtnComponent except for one change. Remove Click Me and add <ng-content> </ng-content> instead. This tag acts as a placeholder. You can also think of it as an argument to the component. The parent component must supply the argument

                              
 
import { Component, Output, EventEmitter } from '@angular/core';
 
@Component({
 selector: 'app-fancybtn',
 template: `
     <button>
       <ng-content></ng-content>
     </button> `
})
export class FancyBtnComponent {
}
 
                            
                        

Now open the app.component.html

                              

<h2>Button Demo With ng-content</h2>
<app-fancybtn>Click Me</app-fancybtn>
<app-fancybtn><b>Submit</b></app-fancybtn>
 
                            
                        

The content between a <pp-fancybtn> </app-fancybtn> is passed to our FancyBtnComponent. The component displays it in place of ng-content.

The advantage of such a solution is that you can pass any HTML content.

image

Events

The events like click,input, etc bubble up. Hence can be captured in the parent as shown below

                              
 
**app.component.html**
 
<h2>Button with click event</h2>
<app-fancybtn (click)="btnClicked($event)"><b>Submit</b></app-fancybtn>
 
 
** App.component.ts ***
 
 btnClicked($event) {
   console.log($event)
   alert('button clicked')
 }
 
                            
                        

But if you have more than one button, then you may have to inspect the $event argument to check, which button responsible for the event.

Custom Events

You can create custom events using the @output as shown in below

                              

@Output,() someEvent:EventEmitter =new EventEmitter();
 
raiseSomeEvent() {
 this.someEvent.emit(args);
}
 
                            
                        

In parent component

                              
 
<app-fancybtn (someEvent)=”DoSomething($event)”><b>Submit</b></app-fancybtn>
                            
                        

Multiple Projections using ng-content

The button example is a very simple example. The ng-content is much more powerful than that. It allows us to create multiple slots in the template. Each slot must define a selector. You can think this as a multiple arguments to the component

In the parent component we can create different contents and each of those contents can be projected into any of those slots depending on their selector. To implement this we make use of the ng-content Select attribute. The select attribute is a CSS Selector

Example of ng-content select attribute

For Example, create a new component card.component.ts

                              

import { Component } from '@angular/core';
 
 
@Component,({
  selector: 'app-card',
  template: `
    <div class="card">
    <div class="header">
      <ng-content select="header" ></ng-content>
    </div>
    <div class="content">
      <ng-content select="content" ></ng-content>
    </div>
    <div class="footer">
      <ng-content select="footer" ></ng-content>
    </div>
    </div>
  `,
  styles: [
    ` .card { min- width: 280px;  margin: 5px;  float:left  } 
      .header { color: blue}
    `
  ]
})
export class CardComponent {
}
 
 
                            
                        

In the above example, we have three ng-content slots, each have a selector header, content & footer

Now open the app.component.html add the following code

                              
 
<app-card>
 <header><h1>Angular</h1></header>
 <content>One framework. Mobile & desktop.</content>
 <footer><b>Super-powered by Google </b></footer>
</app-card>
  
<app-card>
 <header><h1 style="color:red;">React</h1></header>
 <content>A JavaScript library for building user interfaces</content>
 <footer><b>Facebook Open Source </b></footer>
</app-card>
 
                            
                        

Select attribute is a CSS selector

You can use any CSS selector as the select attribute. Like class, element, id attributes, etc. For Example, the above card component using the CSS class

Now open the app.component.html add the following code

                              
 
import { Component } from '@angular/core';
 
@Component,({
  selector: 'card',
  template: `
    <div class="card">
    <div class="header">
      <ng-content select=".header" ></ng-content>
    </div>
    <div class="content">
      <ng-content select=".content" ></ng-content>
    </div>
    <div class="footer">
      <ng-content select=".footer" ></ng-content>
    </div>
    </div>
  `,
  styles: [
    ` .card { width: 280px;  margin: 5px;  float:left; border-width:1px; border-style:solid ; } 
      .header { color: blue}
    `
  ]
})
export class CardComponent {
                            
                        

And in the component, we use it as

                              
 
<card>
  <div class="header">
    <h1>Angular</h1>
  </div>
  <div class="content">One framework. Mobile & desktop.</div>
  <div class="footer"><b>Super-powered by Google </b></div>
</card>
 
<card>
  <div class="header">
    <h1 style="color:red;">React</h1>
  </div>
  <div class="content">A JavaScript library for building user interfaces</div>
  <div class="footer"><b>Facebook Open Source </b></div>
</card>
 
                            
                        

Similarly, you can use the various CSS Selectors as shown below

                              

 <ng-content select="custom-element" ></ng-content>
 <ng-content select=".custom-class" ></ng-content>
 <ng-content select="[custom-attribute]" ></ng-content>
 
                            
                        

ng-content without selector catches all

Now, in the following example, the last paragraph does not belong to any ng-content slots. Hence ng-content will not project the last para as it cannot determine where to add.

                              
 
<card>
  <div class="header"><h1>Typescript</h1></div>
  <div class="content">Typescript is a javascript for any scale</div>
  <div class="footer"><b>Microsoft </b></div>
  <p>This text will not be shown</p>
</card>
 
                            
                        

To solve the above issue, we can include ng-content without any selector. It will display all the content, which cannot be projected into any other slots.

                              

import { Component } from '@angular/core';
 
 
@Component,({
  selector: 'app-card',
  template: `
    <div class="card">
    <div class="header">
      <ng-content select="header" ></ng-content>
    </div>
    <div class="content">
      <ng-content select="content" ></ng-content>
    </div>
    <div class="footer">
      <ng-content select="footer" ></ng-content>
    </div>
    <ng-content></ng-content>                      
    </div>
  `,
  styles: [
    ` .card { min- width: 280px;  margin: 5px;  float:left  } 
      .header { color: blue}
    `
  ]
})
export class CardComponent {
}
 
                            
                        

ngProjectAs

Sometimes it becomes necessary to wrap the component using the ng-container. Most of the time when you use a structural directive like ngIf or ngSwitch.

In the following example, we enclosed the header inside the ng-container.

                              
 
 
<card>
  <ng-container>
    <div class="header">
      <h1 style="color:red;">React</h1>
    </div>
  </ng-container>
  <div class="content">A JavaScript library for building user interfaces</div>
  <div class="footer"><b>Facebook Open Source </b></div>
</card>
 
 
                            
                        

Because of the ng-container, the header section is not projected to the header slot. Instead, it is projected to the ng-content slot which does not have a selector set.

To help in such a scenario, you can make use of ngProjectAs attribute as shown below.

                              

<card>
  <ng-container ngProjectAs="header">
    <div>
      <h1 style="color:red;">React</h1>
    </div>
  </ng-container>
  <div class="content">A JavaScript library for building user interfaces</div>
  <div class="footer"><b>Facebook Open Source </b></div>
</card>
                            
                        

summary

The ng-content allows us to add the external content in the Template. Unlike @Input, using ng-content we can pass the data which includes the HTML elements, CSS, etc, This is also known as content projection. We can also define different slots using the selector attribute. These slots allow us to add different content to different slots.