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

CSS3+HTML5+JS realizes the shrinking and expanding animation effect of a block

When I was working on a project recently, I found...

Detailed explanation of the principle and function of JavaScript closure

Table of contents Introduction Uses of closures C...

Summary of common MySQL commands

Set change mysqlroot password Enter the MySQL dat...

Detailed explanation of MySQL three-value logic and NULL

Table of contents What is NULL Two kinds of NULL ...

Solution to the conflict between Linux kernel and SVN versions

Phenomenon The system could compile the Linux sys...

Docker installation tomcat dubbo-admin instance skills

1. Download the tomcat image docker pull tomcat:8...

How to use vw+rem for mobile layout

Are you still using rem flexible layout? Does it ...

Docker win ping fails container avoidance guide

Using win docker-desktop, I want to connect to co...

JavaScript Shorthand Tips

Table of contents 1. Merge arrays 2. Merge arrays...

How to reset the root password in Linux mysql-5.6

1. Check whether the MySQL service is started. If...

Summary of MySQL common functions

Preface: The MySQL database provides a wide range...

Example of Vue uploading files using formData format type

In Vue, we generally have front-end and back-end ...