现在,我们写一个组件puppiesListCmp,用于显示小狗狗的列表:

//puppies-list.component.ts
@Component({
selector: 'puppies-list',
template: `
<div *ngFor="let puppy of puppies">
<span>{{puppy.name}}</span>
<span>{{puppy.age}}</span>
<span>{{puppy.color}}</span>
</div>
`
})
export class puppiesListCmp{
@Input() puppies: Puppy[];
}
interface Puppy {
name: string,
age: number,
color: string
}

然后这样使用:

//app.component.ts
@Component({
selector: 'my-app',
template: `
<puppies-list [puppies]="puppies"></puppies-list>
`
})
export class App{
puppies = [
{
name: "sam",
age: 0.6,
color: "yellow"
},
{
name: "bingo",
age: 1.5,
color: "black"
}
]
}

效果就行这样:

但是,我希望我们的puppiesListCmp组件可以满足不同的需求,比如在数据不变的情况下只显示小狗狗的name和color,就像这样:

这就是本文的重点了。我们需要实现用户自定义模板!

现在我们不写死组件的模板了,而是让用户从外部输入!

首先,我们的组件模板:

<div *ngFor="let puppy of puppies">
<span>{{puppy.name}}</span>
<span>{{puppy.age}}</span>
<span>{{puppy.color}}</span>
</div>

等价于:

<ng-template ngFor let-puppy [ngForOf]="puppies">
<div>
<span>{{puppy.name}}</span>
<span>{{puppy.age}}</span>
<span>{{puppy.color}}</span>
</div>
</ng-template>

然后,用@ContentChild(关于@ContentChild可以查看这里,需翻墙)获取到外部(相对puppiesListCmp组件而言)自定义模板,并赋给ngForTemplate。也就是说,这部分:

<div>
<span>{{puppy.name}}</span>
<span>{{puppy.age}}</span>
<span>{{puppy.color}}</span>
</div>

不再像之前那样写死在组件里了,而是由使用者在父组件中自定义,然后利用Angular的内容投射(Content Projection),投射到puppiesListCmp组件里面。就像这样:

//puppies-list.component.ts
import { Component, Input, ContentChild, TemplateRef } from '@angular/core';
import { NgForOfContext } from '@angular/common';
@Component({
selector: 'puppies-list',
template: `
<ng-template ngFor let-puppy [ngForOf]="puppies" [ngForTemplate]="tpl"></ng-template>
`
})
export class puppiesListCmp{
@Input() puppies: Puppy[];
@ContentChild(TemplateRef) tpl: TemplateRef<NgForOfContext<Puppy>>
}
interface Puppy {
name: string,
age: number,
color: string
}

这样我们的组件就算完成了。然后我们使用它:

//app.component.ts
@Component({
selector: 'my-app',
template: `
<puppies-list [puppies]="puppies">
<ng-template let-puppy>
<div>
<span>{{puppy.name}}</span>
<span>{{puppy.age}}</span>
<span>{{puppy.color}}</span>
</div>
</ng-template>
</puppies-list>
`
})

效果还是一样的:

如果我们只要显示小狗狗的name和color,只要这样写就好了:

//app.component.ts
@Component({
selector: 'my-app',
template: `
<puppies-list [puppies]="puppies">
<ng-template let-puppy>
<div>
<span>{{puppy.name}}</span>
<span>{{puppy.color}}</span>
</div>
</ng-template>
</puppies-list>
`
})

效果就像这样:

这样的组件很灵活,想要什么样的效果都可以定制,这就实现了组件的复用。

好了,本文就到此为止了。不当之处,欢迎指出!

Angular:利用内容投射向组件输入ngForOf模板的更多相关文章

  1. Angular利用@ViewChild在父组件执行子组件的方法

    代码如下: @Component({ selector: 'my-app', template: ` <step-bar #stepBar></step-bar> ` }) e ...

  2. Angular开发实践(八): 使用ng-content进行组件内容投射

    在Angular中,组件属于特殊的指令,它的特殊之处在于它有自己的模板(html)和样式(css).因此使用组件可以使我们的代码具有强解耦.可复用.易扩展等特性.通常的组件定义如下: demo.com ...

  3. 使用ng-content进行组件内容投射

    原文 https://www.jianshu.com/p/c0a39b1776c0 大纲 1.认识内容投射 2.一个简单组件 3.简单投射 4.针对性投射 5.ngProjectAs 6.代码资源 认 ...

  4. vue组件4 利用slot将内容传递给组件

    除了将数据作为prop传入到组件中,vue也允许传入HTML 父组件中的子组件:<custom-button>点我<custom-button/> custom-button子 ...

  5. 转载——利用C#自带组件强壮程序日志

    利用C#自带组件强壮程序日志   在项目正式上线后,如果出现错误,异常,崩溃等情况 我们往往第一想到的事就是查看日志 所以日志对于一个系统的维护是非常重要的 声明 正文中的代码只是一个栗子,一个非常简 ...

  6. Vue中利用$emit实现子组件向父组件通信

    Vue中利用$emit实现子组件向父组件通信 父组件 <template> <div> <p>我是父组件</p> <child :isShow=& ...

  7. EditTextPreference点击后输入框显示隐藏内容,类似密码输入(转)

    http://bbs.anzhuo.cn/thread-928131-1-1.html EditTextPreference点击后输入框显示隐藏内容,类似密码输入... [复制链接]     aski ...

  8. angular利用ui-router登录检查

    angular利用ui-router登录检查 SAP都会有这个问题,session过期或者页面被刷新的情况下应该进入登录页. 监听ui-router的satte事件可以实现当state切换的时候检查登 ...

  9. Java学习笔记之[ 利用扫描仪Scanner进行数据输入 ]

    /*********数据的输入********//**利用扫描仪Scanner进行数据输入 怎么使用扫描仪Scanner *1.放在类声明之前,引入扫描仪 import java.util.Scann ...

随机推荐

  1. Switch-case 内定义变量的问题

    Switch-case 内定义变量的问题 这个问题需要分开讨论,C 语言和 C++ 的标准定义是不同的. C++ int Caset(int a) { switch (a) { case 1: int ...

  2. mybatis传参的几种方式

    1,@Param @参考文章 @Select("select s_id id,s_name name,class_id classid from student where  s_name= ...

  3. docker挂载NVIDIA显卡运行pytorch

    本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃   写在前面: 请参考之前的文章安装好CentOS.NVIDIA相关驱动及软件.docker及 ...

  4. Python字典(dict)使用技巧

    字典dict是Python中使用频率非常高的数据结构,关于它的使用,也有许多的小技巧,掌握这些小技巧会让你高效地的使用dict,也会让你的代码更简洁. 1.默认值 假设name_for_userid存 ...

  5. Round trip 流程图

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢!

  6. 【django之form表单】

    一.构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的模板: <form action="/your-name/" method=&qu ...

  7. [偏序关系与CDQ分治]【学习笔记】

    组合数学真是太棒了 $CDQ$真是太棒了(雾 参考资料: 1.<组合数学> 2.论文 课件 很容易查到 3.sro __stdcall 偏序关系 关系: 集合$X$上的关系是$X$与$X$ ...

  8. C#之文件缓存

    写在开头 今天就放假了,照理说应该写今年的总结了,但是回头一看,很久没有写过技术类的文字了,还是先不吐槽了. 关于文件缓存 写了很多的代码,常常在写EXE(定时任务)或者写小站点(数据的使用和客户端调 ...

  9. Vue打包后出现一些map文件

    Vue打包后出现一些map文件的解决办法: 问题: 可能很多人在做vue项目打包,打包之后js中,会自动生成一些map文件,那我们怎么把它去掉不要呢? 1,运行  cnpm run build  开始 ...

  10. 使用scrapy爬取豆瓣上面《战狼2》影评

    这几天一直在学习scrapy框架,刚好学到了CrawlSpider和Rule的搭配使用,就想着要搞点事情练练手!!! 信息提取 算了,由于爬虫运行了好几次,太过分了,被封IP了,就不具体分析了,附上& ...