Html ngIf为false时生成Angular4 ng内容

Html ngIf为false时生成Angular4 ng内容,html,angular,typescript,angular2-template,Html,Angular,Typescript,Angular2 Template,我对新的ng内容transclusion有问题 假设我有一个组件mycomponent,它在ngOnInit()函数中执行一些重载操作(目前,它只是一个console.log()) 我有一个包装器,它通过转换显示内容(my wrapper.component.html) 我总是看到console.log()输出。我猜,mycomponent被构建,然后被存储起来,直到*ngIf变成true在mywrapper中 其目的是构建一个通用的“列表项+细节”组件。假设我有一个N个概览元素的列表(mywr

我对新的
ng内容
transclusion有问题

假设我有一个组件
mycomponent
,它在
ngOnInit()
函数中执行一些重载操作(目前,它只是一个
console.log()

我有一个包装器,它通过转换显示内容(
my wrapper.component.html

我总是看到
console.log()
输出。我猜,
mycomponent
被构建,然后被存储起来,直到
*ngIf
变成
true
mywrapper

其目的是构建一个通用的“列表项+细节”组件。假设我有一个N个概览元素的列表(
mywrapper
),这些元素在
*ngFor
循环中呈现。这些元素中的每一个都有自己的细节组件(
mycomponent
),一旦我决定向特定项目显示更多信息,这些组件就应该加载自己的数据

overview.html:

<ng-container *ngFor="let item of items">
    <my-wrapper>
        <my-component id="item.id"></my-component>
    </my-wrapper>
</ng-container>

my-wrapper.component.html:

<div (click)="toggleDetail()">Click for more</div>
<div *ngIf="showDetail">
    <ng-content></ng-content>
</div>
点击查看更多信息
有没有办法告诉Angular,在需要添加到页面之前忽略转置的内容?类似于AngularJS中的情况。

通过这样做:

<my-wrapper *ngIf="false">
    <my-component></my-component>
</my-wrapper>
<ng-container *ngIf="false">
    <ng-content></ng-content>
</ng-container>
您在组件内部,您只是在限制在模板中渲染的内容,但您已经实例化了组件,因此,您通过了
ngOnInit
,并完成了控制台日志

如果要限制某些内容(使用选择器的组件调用或
ng content
或甚至
div
),直到有一些数据可用,可以执行以下操作:

datasLoaded: Promise<boolean>;

this.getData().subscribe(
       (data) => {
            this.datasLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data
       }
);
数据加载:承诺;
这是.getData().subscribe(
(数据)=>{
this.datasload=Promise.resolve(true);//在获得所需数据后将承诺设置为已解析
}
);
在模板中:

<ng-container *ngIf="datasLoaded | async">
   // stuff here
</ng-container>

//这里的东西
或:


//没有测试这个,但是应该遵循相同的逻辑。如果没有,则包装它并将ngIf添加到包装器中

根据@nsinreal的评论,我找到了答案。我觉得它有点深奥,所以我试着把它贴在这里:

答案是使用
ng template
*ngTemplateOutlet

mywrapper
组件中,按如下方式设置模板(
mywrapper.component.html
):

现在,您可以像这样使用包装器:

<my-wrapper>
    <ng-template>
        <my-component></my-component>
    </ng-template>
</my-wrapper>


我不知道为什么它需要如此复杂的“变通方法”,而在AngularJS中这样做很容易。

这是因为Ng内容发生在构建时,当您传递内容时,它实际上没有被删除或用ngIf指令重新创建。它只被移动,组件被实例化。

我最近也遇到了这个问题,但解决方案与当前接受的不同

解决方案(TL;DR) (解决方案是针对AngularDart;我认为它在角度上是相似的)

使用结构指令;教程链接如下

而不是:


您的使用变成:


这是以下内容的简写(在AngularDart中;我认为Angular使用


MyWrapper
指令逻辑与
NgIf
类似,只是它有自己的逻辑来计算条件。以下两个教程都解释了如何创建类似NgIf的指令,以及如何使用特殊的microsyntax(例如
*myWrapper=“myInput:expression”
)将自己的输入传递给用户。请注意,microsyntax不支持输出(
@Output
),但您可以使用作为函数的输入来模拟输出

注意事项:由于这只是一个指令,它不应该做比在适当的时间实例化模板引用和指定一些DI提供程序更复杂的事情。例如,我将避免尝试在指令中应用样式或实例化复杂的组件树。如果我想创建一个列表组件,我可能会采用另一个答案中描述的
@ContentChild(TemplateRef)
方法;您将失去创建
的星号速记,但您将获得组件的全部功能

我的问题 我的团队拥有一个属于大型web应用程序的应用程序,其他团队拥有其他应用程序。我们的组件假定它们可以注入一个
MyAppConfiguration
对象,但是这个对象只有在加载异步请求后才能被注入。在我们的应用程序中,这不是一个问题:我们有一个“shell”组件,它将所有内容隐藏在
ngIf
后面,直到加载配置

问题是当其他团队想要引用我们的组件时。我们不希望他们每次都重复“等待配置加载”逻辑,因此我尝试创建一个包装器组件,可以像这样使用:


包装器注入服务对象并将其内容隐藏在
ngIf
后面,直到服务表示已加载配置

与问题海报一样,我发现
ng content
方法没有按预期工作:虽然内容正确地隐藏在DOM中,但Angular仍然实例化了导致依赖注入失败的组件


我决定的解决方案是将包装器组件重写为结构指令。

我建议不要在包装器上添加条件,而是将条件添加到子组件以停止执行。我认为这在我的情况下不起作用。这样做的目的是:我有一个概览数据列表,在
*ngFor
-循环(
mywrapper
)中呈现。对于每个概述项目,我都有第二个“细节”组件(
my component
),即
datasLoaded: Promise<boolean>;

this.getData().subscribe(
       (data) => {
            this.datasLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data
       }
);
<ng-container *ngIf="datasLoaded | async">
   // stuff here
</ng-container>
<my-component *ngIf="datasLoaded | async">
   // Didn't test this one, but should follow the same logic. If it doesn't, wrap it and add the ngIf to the wrapper
</my-component>
<div (click)="toggleDetail()">Click for more</div>
<div *ngIf="showDetail" [hidden]="!isInitialized">
    <ng-container *ngTemplateOutlet="detailRef"></ng-container>
</div>
import { ContentChild, TemplateRef } from '@angular/core';

@Component({ ... })
export class MyWrapperComponent {
    @ContentChild(TemplateRef) detailRef;

    ...
}
<my-wrapper>
    <ng-template>
        <my-component></my-component>
    </ng-template>
</my-wrapper>