Detailed explanation of angular content projection

Detailed explanation of angular content projection

Single content projection

Using ng-content to implement

<!-- Component- app-content-single -->
<div>
  <h2>Title</h2>
  <!-- Projection content display position-->
  <ng-content></ng-content>
</div>
<!-- Usage -->
<app-content-single>
  <div>this is content</div>
</app-content-single>

Multi-content projection

Using ng-content to implement

<!-- Component- app-content-more -->
<div>
  <h3>Herder Title</h3>
  <ng-content select=".header"></ng-content>
  <h3>Body Title</h3>
  <ng-content select="[body]"></ng-content>
  <h3>Default Title</h3>
  <ng-content></ng-content>
  <h3>Footer Title</h3>
  <ng-content select="footer"></ng-content>
</div>
<!-- Usage -->
<app-content-more>
  <div>this is default01</div>
  <div class="header">this is header</div>
  <div>this is default02</div>
  <div body>this is body</div>
  <div>this is default03</div>
  <footer>this is footer</footer>
  <div>this is default04</div>
</app-content-more>

Conditional content projection - ng-template , ng-container , directive , etc. to achieve

Content projection for a single condition

For example: suppose there is a list of people now. When the money of a person is greater than 200, the content defined in the template in the component is added

Define an appChildRef directive to cooperate with ng-template to obtain the template

import { Directive, TemplateRef } from '@angular/core';
@Directive({
  selector: '[appChildRef]'
})
export class ChildRefDirective {
  constructor(public templateRef: TemplateRef<any>) { }
}

app-persons-html

<div class="list-item" *ngFor="let person of persons;">
  <div>Name: {{ person.name }}</div>
  <div>Money: {{ person.money }}</div>
  <div *ngIf="person.money > 200">
    <ng-container *ngIf="childRef" [ngTemplateOutlet]="childRef.templateRef"></ng-container>
  </div>
</div>

app-persons - ts

import { Component, ContentChild, OnInit } from '@angular/core';
import { ChildRefDirective } from '../../../../directives/child-ref.directive';
@Component({
  selector: 'app-persons',
  templateUrl: './persons.component.html',
  styleUrls: ['./persons.component.scss']
})
export class PersonsComponent implements OnInit {
  persons: { name: string; money: number; }[] = [
    { name: 'Jack', money: 120 },
    { name: 'Li Li', money: 210 },
    { name: 'Zhang San', money: 170 },
  ];
  @ContentChild(ChildRefDirective, { static: true }) childRef!: ChildRefDirective;
  constructor() { }
  ngOnInit(): void { }
}

use

<app-persons>
  <ng-template appChildRef>
    <div style="font-size: 14px; color: red;">this is child ref content</div>
  </ng-template>
</app-persons>

Rendering

Rendering

Multiple conditional content projection

Eg: Now we want to bind the embedded template to display through the fields in the persons data

appChildRef Adjustment

import { Directive, Input, TemplateRef } from '@angular/core';
@Directive({
  selector: '[appChildRef]'
})
export class ChildRefDirective {
  // Accept the defined template name - display the corresponding template content through this name and the render field in persons @Input() appChildRef!: string;
  constructor(public templateRef: TemplateRef<any>) { }
}

app-persons-html

<div class="list-item" *ngFor="let person of persons;let i=index;">
  <div>Name: {{ person.name }}</div>
  <div>Money: {{ person.money }}</div>
  <!-- <div *ngIf="person.money > 200">
    <ng-container *ngIf="childRef" [ngTemplateOutlet]="childRef.templateRef"></ng-container>
  </div> -->
  <div *ngIf="person.render && tempRefs[person.render]">
    <!-- Use the ngTemplateOutlet directive to pass the current person data to the template -->
    <ng-container *ngTemplateOutlet="tempRefs[person.render].templateRef; context: { $implicit: person, i: i }"></ng-container>
  </div>
</div>

app-persons - ts

import { Component, ContentChild, ContentChildren, OnInit, QueryList } from '@angular/core';
import { ChildRefDirective } from '../../../../directives/child-ref.directive';
@Component({
  selector: 'app-form-unit',
  templateUrl: './form-unit.component.html',
  styleUrls: ['./form-unit.component.scss']
})
export class FormUnitComponent implements OnInit {
  persons: { name: string; money: number; render?: string; }[] = [
    { name: 'Jack', money: 120, render: 'temp1' },
    { name: '李莉', money: 210, render: 'temp2' },
    { name: '张三', money: 170, render: 'temp3' },
  ];
  // @ContentChild(ChildRefDirective, { static: true }) childRef!: ChildRefDirective;
  @ContentChildren(ChildRefDirective) childrenRef!: QueryList<ChildRefDirective>;
  get tempRefs() {
    const aObj: any = {};
    this.childrenRef.forEach(template => {
      const key: string = template.appChildRef;
      aObj[key] = template;
    })
    return aObj;
  }
  constructor() { }
  ngOnInit(): void { }
}

use

<app-persons>
  <ng-template appChildRef="temp1" let-person let-index="i">
    <div style="font-size: 14px; color: red;">{{index}}-{{person.name}}: this is temp1</div>
  </ng-template>
  <ng-template appChildRef="temp2" let-person let-index="i">
    <div style="font-size: 14px; color: green;">{{index}}-{{person.name}}: this is temp2</div>
  </ng-template>
  <ng-template appChildRef="temp3" let-person let-index="i">
    <div style="font-size: 14px; color: orange;">{{index}}-{{person.name}}: this is temp3</div>
  </ng-template>
</app-persons>

Rendering

Rendering

Summarize

This article ends here. I hope it can be helpful to you. I also hope you can pay more attention to more content on 123WORDPRESS.COM!

You may also be interested in:
  • Detailed explanation of Angular component projection
  • Detailed explanation of the implementation of shared modules in Angular projects
  • Detailed explanation of Angular routing sub-routes
  • Detailed explanation of Angular routing basics
  • Detailed explanation of the life cycle of Angular components (Part 2)
  • Detailed explanation of Angular component life cycle (I)
  • Detailed explanation of the middleman mode of Angular components

<<:  How to reduce the root directory of XFS partition format in Linux

>>:  SQL Aggregation, Grouping, and Sorting

Recommend

Try Docker+Nginx to deploy single page application method

From development to deployment, do it yourself Wh...

Analysis of MySQL example DTID master-slave principle

Table of contents 1. Basic Concepts of GTID 2. GT...

The Complete List of MIME Types

What is MIME TYPE? 1. First, we need to understan...

Detailed explanation of the four transaction isolation levels in MySQL

The test environment of this experiment: Windows ...

MySQL table and column comments summary

Just like code, you can add comments to tables an...

Vue project code splitting solution

Table of contents background Purpose Before split...

Talking about Less and More in Web Design (Picture)

Less is More is a catchphrase for many designers....

JavaScript setTimeout and setTimeinterval use cases explained

Both methods can be used to execute a piece of ja...

How to move a red rectangle with the mouse in Linux character terminal

Everything is a file! UNIX has already said it. E...

Docker-compose installation yml file configuration method

Table of contents 1. Offline installation 2. Onli...

JavaScript implements password box input verification

Sometimes it is necessary to perform simple verif...

Detailed explanation of the background-position percentage principle

When I was helping someone adjust the code today,...