- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我们正在构建一个 angular 4 组件库,其中一个组件是 Busy 组件。该组件的目的是允许开发人员在任何包含微调器图形的给定 HTML 元素上创建叠加层。
<div *xuiBusy="isBusy">...</div>
当值isBusy
是真的我们想追加到 div
的内部内容这样我们就可以在内容之上呈现叠加元素。
我们已经能够将组件附加到 ViewContainerRef
然而,这会将 busy 元素作为 div
的兄弟元素插入而不是在 div
内随心所欲。
ngOnInit(): void {
const compFactory = this._componentFactory.resolveComponentFactory(XuiBusyComponent);
const comp = this._viewContainer.createComponent(compFactory);
消费者做什么:
<div *xuiBusy="isBusy">
<span>This is the content</span>
</div>
当 isBusy
设置为 true 我们希望将标记更改为如下所示。注意 <spinner>
已添加到 div
元素。
<div *xuiBusy="isBusy">
<span>This is the content</span>
<spinner>Please wait...</spinner> <-- inserted by directive
</div>
感谢任何建议!
最佳答案
我已经设置了 a demo on StackBlitz .为简洁起见,Spinner 组件、Busy 指令和消费者都在 app.component.ts
中。
结构指令需要注入(inject)以下内容:
TemplateRef
, 对结构指令所在模板的引用(在脱糖语法中);ViewContainerRef
,对 View 容器的引用,可以在结构指令封装的 View 内呈现;ComponentFactoryResolver
,一个知道如何从代码动态创建组件实例的类。Angular 中的注入(inject)是通过构造函数完成的。
constructor(private templateRef: TemplateRef<void>,
private vcr: ViewContainerRef,
private cfr: ComponentFactoryResolver) { }
我们需要输入以便从外部传递数据。为了使语法漂亮和明显(特别是当指令需要单个输入时,例如在本例中),我们可以将输入命名为与指令选择器完全相同的名称。
要重命名输入,我们可以传递 bindingPropertyName
到 Input
装饰器。
@Input('xuiBusy') isBusy: boolean;
可以使用 createEmbeddedView
动态创建消费者的内容在 ViewContainerRef
类上定义的方法。第一个参数是唯一的强制参数,它接受一个模板引用,插入的 View 将基于该模板引用:这是我们在我们的案例中注入(inject)的 templateRef
。
this.vcr.createEmbeddedView(this.templateRef)
动态创建组件需要更多仪式,因为您首先需要解析知道如何跨越组件实例的工厂。
为此,我们使用 resolveComponentFactory
注入(inject)的 ComponentFactoryResolver
实例上的方法。
const cmpFactory = this.cfr.resolveComponentFactory(SpinnerComponent)
现在我们可以使用生成的工厂来以与创建嵌入式 View 类似的方式createComponent
。
this.vcr.createComponent(cmpFactory)
当然,这只有在 isBusy
标志设置为 true
时才会发生,因此我们将其包装在一个分支中。
if (this.isBusy) {
const cmpFactory = this.cfr.resolveComponentFactory(SpinnerComponent)
this.vcr.createComponent(cmpFactory)
}
Angular 需要先编译我们的组件,然后才能在应用程序中使用它们。如果组件从未在模板中被引用,Angular 将不知道它需要编译它。我们的 Spinner 组件就是这种情况,因为我们只是从代码中动态添加它。
要明确告诉 Angular 编译组件,请将其添加到 NgModule.entryComponents
。
@NgModule({
...
entryComponents: [SpinnerComponent],
...
})
@Directive({selector: '[xuiBusy]'})
export class BusyDirective implements OnInit {
@Input('xuiBusy') isBusy: boolean;
constructor(private templateRef: TemplateRef<void>,
private vcr: ViewContainerRef,
private cfr: ComponentFactoryResolver) { }
ngOnInit() {
this.vcr.createEmbeddedView(this.templateRef)
if (this.isBusy) {
const cmpFactory = this.cfr.resolveComponentFactory(SpinnerComponent)
this.vcr.createComponent(cmpFactory)
}
}
}
<div *xuiBusy="true">
<span>This is some content</span>
</div>
<div *xuiBusy="false">
<span>This is some content</span>
</div>
关于angular - 使用结构指令将组件添加到 TemplateRef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43944487/
我正在尝试构建一个多选组件,它可以为每个选择选项元素提供一个模板。它大部分都在工作,模板是从选项组件中的 ng-content 中获取的,并显示在“选择弹出框”中。 尝试在选择组件中显示所选选项时遇到
我正在尝试创建一个根据条件创建 View 的指令。就像内置的 ngIf 指令一样。 这是我添加到项目中的所有内容: export class QueryNameContext { public
如果答案是已接受的答案,我会尝试显示复选标记: template: `✔` 但是我得到这个错误: EXCEPTION: No provider for TemplateRef! (NgI
也许我从根本上误解了某些东西,但我试图让 TemplateRef 指向我的组件的模板(在下面的简单示例中只是“Hello”)。我已将我的代码精简到最低限度以尝试找出问题所在: import { Com
也许我从根本上误解了某些东西,但我试图让 TemplateRef 指向我的组件的模板(在下面的简单示例中只是“Hello”)。我已将我的代码精简到最低限度以尝试找出问题所在: import { Com
我希望将组件的 ng-content 的内部文本作为简单字符串获取,以便能够重用它。 我尝试过这样的事情: @Component({ selector: 'my-comp', template
我必须将所有 ngx-bootstrap modals 放在一个 component.html 中,这样我就可以从任何地方访问任何模态。 我试过下面的代码 header.componentn.html
最近我开始积极使用模板来自定义我的 UI 组件。我还使用 OnPush 变化检测策略来优化性能。如果我将模板传递给嵌套组件,一切都会顺利进行。用户操作触发嵌套组件中的更改检测,它向上移动到定义模板的原
我在创建基于自定义 Observable 和自定义项目 TemplateRef 呈现项目集合的组件时遇到问题。 该组件将 Observable 和 TemplateRef 作为输入并适本地呈现它们。问
有没有办法为服务中的现有 html 模板获取 TemplateRef? 问题的背景(因为我一开始可能做错了什么): 我正在创建一个使用 NgbModal 的服务在弹出窗口中显示一些文本。模态需要一个
我们正在构建一个 angular 4 组件库,其中一个组件是 Busy 组件。该组件的目的是允许开发人员在任何包含微调器图形的给定 HTML 元素上创建叠加层。 ... 当值isBusy是真的我们想追
我对如何通过传递 string 来获取 TemplateRef 很感兴趣。 我不想通过组件 html 获取它,因为我只想将它保存在配置中以供所有组件使用。我指的是可以在此处查看的 ng-bootstr
组件 HTML: 组件 TS: @ViewChild('content') public content: TemplateRef; Visual Studio 消息: [ts] Generic
最近我有一个任务,我需要将一个 TemplateRef 传递给组件,它提供一些服务,比如 SomeService。在该模板中,我使用了一个注入(inject)服务 SomeService 的指令。我最
我试图改进我的代码而不是有条件,所以我决定创建一个指令或者如果可能的话创建一个管道,它可以帮助我根据其类型(字符串或模板引用)打印选项卡的标题,我的代码如下,此代码用于我的 Tabs/Tab 组件
我得到的组件 假设我有以下 super 简单的组件: class MyComponent { @Input() simpleContent: string; @ContentC
让我们假设我有显示数据列表的泛型类型的组件: interface DataProvider { getData(): T[]; } ... template: ' ' ...
在 Angular 中试验 ElementRef、TemplateRef、ViewRef 和 ViewContainerRef。我已经创建了一个 HTML 模板,我想从那里创建一个 View 并将该
我正在尝试获取 ng-template 和 input 参数的 TemplateRef。 应用程序组件.html: {{dataItem|json}} 问题是我
我想使用 ViewChildren 从 TemplateRef 生成 QueryList,但无法传递到输入组件。 例如 组件.ts: @ViewChildren(TemplateRef) cellTe
我是一名优秀的程序员,十分优秀!