Angular 中使用 ChildContent 记录

news/2025/1/8 11:31:03/文章来源:https://www.cnblogs.com/dudu/p/18658870

记录一下学习使用 ChildContent 的试验代码,用的是 Angular 19。

AppComponent 是 parent component, SidebarComponent 是 child component,SidebarBlogCategoriesComponent 是 projected component 。

代码1:使用 ng-content 在 child component 中显示 projected component 的内容


// SidebarBlogCategoriesComponent
@Component({selector: 'cnb-sidebar-blog-categories',template: `<h1>Hello, World!</h1>`
})
export class SidebarBlogCategoriesComponent implements OnInit {constructor() { }ngOnInit() { }
}// SidebarComponent
@Component({selector: 'cnb-sidebar',template: `<p>SidebarComponent</p><ng-content></ng-content>`
})
export class SidebarComponent implements OnInit {@ContentChild(SidebarBlogCategoriesComponent) content?: SidebarBlogCategoriesComponent;constructor() { }ngOnInit() { }ngAfterContentInit(): void {console.log('content: ' +   this.content);}
}// AppComponent
@Component({selector: 'app-root',imports: [SidebarComponent, SidebarBlogCategoriesComponent],template: `<p>AppComponent</p><cnb-sidebar><cnb-sidebar-blog-categories></cnb-sidebar-blog-categories></cnb-sidebar>`
})
export class AppComponent {
}

运行时页面显示结果:

AppComponent

SidebarComponent

Hello, World!

代码2:Directive + TemplateRef 无法显示 projected component 的内容

这是园子博客后台从 angular 15 升级到 angular 19 后遇到的问题,详见 https://q.cnblogs.com/q/151579

注:下面的代码中用 [ngTemplateOutlet] 取代了 <ng-content>

import { NgIf, NgTemplateOutlet } from '@angular/common';
import { Component, ContentChild, Directive, OnInit, TemplateRef } from '@angular/core';// SidebarContentDirective
@Directive({selector: '[cnbSidebarContent]',
})
export class SidebarContentDirective {constructor(public templateRef: TemplateRef<any>) { }
}// SidebarBlogCategoriesComponent
@Component({selector: 'cnb-sidebar-blog-categories',template: `<h1>Hello, World!</h1>`
})
export class SidebarBlogCategoriesComponent implements OnInit {constructor() { }ngOnInit() { }
}// SidebarComponent
@Component({selector: 'cnb-sidebar',imports: [NgIf, NgTemplateOutlet],template: `<p>SidebarComponent</p><div class="sidebar-content" *ngIf="content && content.templateRef"><ng-container [ngTemplateOutlet]="content.templateRef"></ng-container></div>`
})
export class SidebarComponent implements OnInit {@ContentChild(SidebarContentDirective) content?: SidebarContentDirective;constructor() { }ngOnInit() { }ngAfterContentInit(): void {console.log('content: ' + JSON.stringify(this.content));}
}@Component({selector: 'app-root',imports: [SidebarComponent, SidebarBlogCategoriesComponent],template: `<p>AppComponent</p><cnb-sidebar><cnb-sidebar-blog-categories *cnbSidebarContent></cnb-sidebar-blog-categories></cnb-sidebar>`
})
export class AppComponent {
}

页面输出:

AppComponent

SidebarComponent

console.log 的输出:

content: undefined

代码3:通过 ng-template 引用变量解决 Directive + TemplateRef 的问题

解决方法来自 stackoverflow 上 Angular content projection in standalone component 问题的回答:

We cannot use a directive on ng-template since it does not fire, ng-template is a virtual element and is not rendered in the DOM, so the better option, is to just create template reference variables like #cardHeader and #cardMainContent and access these through ContentChild and directly render them on the HTML.

@ContentChild('cardMainContent') cardMainContent!: TemplateRef<any>;
@ContentChild('cardHeader') cardHeader!: TemplateRef<any>;

解决问题的示例代码:

import { NgIf, NgTemplateOutlet } from '@angular/common';
import { Component, ContentChild, Directive, OnInit, TemplateRef } from '@angular/core';// SidebarBlogCategoriesComponent
@Component({selector: 'cnb-sidebar-blog-categories',template: `<h1>Hello, World!</h1>`
})
export class SidebarBlogCategoriesComponent implements OnInit {constructor() { }ngOnInit() { }
}// SidebarComponent
@Component({selector: 'cnb-sidebar',imports: [NgIf, NgTemplateOutlet],template: `<p>SidebarComponent</p><div class="sidebar-content" *ngIf="content && content"><ng-container [ngTemplateOutlet]="content"></ng-container></div>`
})
export class SidebarComponent implements OnInit {@ContentChild('sidebarContent') content?: TemplateRef<any>;constructor() { }ngOnInit() { }ngAfterContentInit(): void {console.log('content: ' + JSON.stringify(this.content?.elementRef));}
}@Component({selector: 'app-root',imports: [SidebarComponent, SidebarBlogCategoriesComponent],template: `<p>AppComponent</p><cnb-sidebar><ng-template #sidebarContent><cnb-sidebar-blog-categories></cnb-sidebar-blog-categories></ng-template></cnb-sidebar>`
})
export class AppComponent {
}

页面显示结果:

AppComponent

SidebarComponent

Hello, World!

console.log 的输出:

content: {"nativeElement":{"__ngContext__":1}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/865811.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp 荣耀手机 没有检测到设备 运行到Android手机 真机运行

背景: 使用uniapp框架搭建的项目,开发的时候在浏览器运行,因为项目要打包成App,所以需要真机联调,需要运行到Android手机,在手机上查看/运行项目。通过真机调试才能确保软件开发的准确性和页面显示的完整性。操作步骤:1.Usb连接手机和电脑,电脑上的HbuilderX打开项目;…

DC-5 靶场通关小记

rustscan端口扫描指纹识别、LFI漏洞+文件包含(nginx日志)GetShell、screen-4.5.0提权地址 https://www.vulnhub.com/entry/dc-5,314/环境配置 有兼容性问题参考 https://www.cnblogs.com/lrui1/p/18655388 信息收集 ./rustscan -a 192.168.74.130 -- -A -sC Open 192.168.74.13…

ABB IRB5500喷涂机械手维修细节查看

ABB IRB5500喷涂机器人的控制柜常见故障表现形式主要包括以下几种:1、控制柜不能启动:可能原因包括电源故障、控制电路板损坏、保险丝烧断等。处理方法包括检查电源是否正常、控制电路板是否有损坏迹象、保险丝是否烧断等。 2、abb涂装机械手控制柜报错或异常:可能原因包括…

新年新机遇:跨境电商选品策略大揭秘

跨境电商在进行新年选品时,需要综合考虑市场调研、竞争对手分析、品牌选择、价格定位、物流考虑、汇率研究、多元化产品线以及节日和特殊事件等多个因素。通过精心策划和准备,可以确保所选产品在新年期间取得良好的销售业绩。在进行跨境电商新年选品时,需要考虑多个因素以确…

年度重磅 |《2024华为开发者宝典》免费下载,多维度解读华为根生态技术

摘要:20多位华为云DTSE专家打造,10+技术领域全覆盖,图文干货+视频讲解,多维度解读华为根生态技术,拥抱技术变革,开启创新之旅。 一年一度!大家最期待的华为开发者宝典新鲜出炉!在刚刚过去的2024年,华为云开发者联盟通过25场精彩的DTSE Tech Talk直播活动,为广大开发者…

WPF页面中将一个控件的宽度绑定到其父级用户控件的实际宽度

通常情况下,使用相对宽度(如 * 星号单位)和适当的 HorizontalAlignment 是最简单有效的方法,可以确保子控件随着父控件的大小变化而自动调整。如果需要更精确的控制,可以考虑使用 RelativeSource 绑定或其他高级技术。确保父容器也支持子控件的动态尺寸调整非常重要。该实…

Windows 系统下 Docker 和 Docker Compose 安装配置:一键部署有来开源项目本地环境

在 Windows 系统上安装 Docker 和 Docker Compose,实现一键部署有来开源项目的本地环境,包括单体应用和微服务架构。🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🍃 vue-uniapp-template 🌺 仓库主页: GitCod…

Openfiler iscsi共享存储连接访问配置

Openfiler、iscsi案例说明: 通过openfiler虚拟机模拟iscsi server建立存储共享,测试多路径(multipath)配置。 测试架构:iscsi server网络配置:一、通过firefox浏览器访问openfiler服务配置 1、连接服务配置失败2、修改TLS认证级别3、连接访问openfiler配置服务二、配置op…

SQL Server数据库备份、差异备份、日志备份脚本.250108

1,sp脚本 USE [master] GO /****** Object: StoredProcedure [dbo].[sp_BackupDatabase] Script Date: 2025/1/8 10:43:05 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO-- Author: Amadeus-- Create date: 2021-10-20 exec sp_BackupDatabase L-- Descrip…

JuiceFS 2024:开源与商业并进,迈向 AI 原生时代

即将过去的 2024 年,是 JuiceFS 开源版本推出的第 4 年,企业版的第 8 个年头。回顾过去这一年,JuiceFS 社区版依旧保持着快速成长的势头,GitHub 星标突破 11.1K,各项使用指标增长均超过 100%,其中文件系统总数量较前一年更是增长了 8.5 倍;企业版同样持续保持高速增长,…

智慧防洪平台:构建城市安全的数字防线

随着全球气候变化的加剧和城市化进程的加快,城市防洪问题日益凸显。智慧防洪平台作为智慧城市建设的重要组成部分,其核心目标是通过集成先进的信息技术和数据分析,实现对城市洪涝灾害的有效预防和应对。本文将深入探讨智慧防洪平台的建设内容,以期为城市安全提供强有力的数…

如何通过数据分析优化电商营销策略和客户体验

一、电商数据的收集 电商平台的数据来源多样,包括用户行为数据、交易数据、客户反馈数据、商品信息数据等。高效的数据收集不仅是数据分析的前提,也是实现精准决策的基础。 1.1 数据收集的主要来源 用户行为数据:用户在电商平台上的每一次点击、浏览、搜索、加入购物车、下单…