理想情况下,我需要重新加载/重新渲染我的组件模板,但如果有更好的方法来做到这一点,我会很乐意实现它。
期望的行为:
所以,我有一个菜单元素组件。当(在另一个组件中)我点击一个 IBO (某种“客户”,比如说) 被点击时,我需要添加(我我正在使用 *ngIf
) 菜单中的一个新选项,即 IBO 详细信息 和一个子列表。
IBOsNavigationElement
组件(菜单组件):
@Component({
selector: '[ibos-navigation-element]',
template: `
<a href="#"><i class="fa fa-lg fa-fw fa-group"></i> <span
class="menu-item-parent">{{'IBOs' | i18n}}</span>
</a>
<ul>
<li routerLinkActive="active">
<a routerLink="/ibos/IBOsMain">{{'IBOs Main' | i18n}} {{id}}</a>
</li>
<li *ngIf="navigationList?.length > 0">
<a href="#">{{'IBO Details' | i18n}}</a>
<ul>
<li routerLinkActive="active" *ngFor="let navigatedIBO of navigationList">
<a href="#/ibos/IboDetails/{{navigatedIBO['id']}}">{{navigatedIBO['name']}}</a>
</li>
</ul>
</li>
</ul>
`
})
export class IBOsNavigationElement implements OnInit {
private navigationList = <any>[];
constructor(private navigationService: NavigationElementsService) {
this.navigationService.updateIBOsNavigation$.subscribe((navigationData) => {
this.navigationList.push(navigationData);
log.d('I received this Navigation Data:', JSON.stringify(this.navigationList));
}
);
}
ngOnInit() {
}
}
最初,navigationList
将为空 []
,因为用户没有点击任何 IBO (客户),但是一旦点击 IBO,列表就会被填充,因此,我需要新选项出现在菜单中。
使用此代码,当我单击 IBO 时,<li>
元素及其子元素已创建但是:我只看到 <li>
元素。
问题:
菜单选项生成但不由布局样式处理。它需要用所有元素初始化,以便知道如何显示菜单选项。
我需要重新加载该组件的模板才能正确显示菜单。
注意:
如果我使用没有 *ngIf
的模板, 效果很好,但从一开始我就会有一个没有意义的 IBO 详细信息 选项,因为在初始化时没有点击 IBO。
template: `
<a href="#"><i class="fa fa-lg fa-fw fa-group"></i> <span
class="menu-item-parent">{{'IBOs' | i18n}}</span>
</a>
<ul>
<li routerLinkActive="active">
<a routerLink="/ibos/IBOsMain">{{'IBOs Main' | i18n}} {{id}}</a>
</li>
<li>
<a href="#">{{'IBO Details' | i18n}}</a>
<ul>
<li routerLinkActive="active" *ngFor="let navigatedIBO of navigationList">
<a href="#/ibos/IboDetails/{{navigatedIBO['id']}}">{{navigatedIBO['name']}}</a>
</li>
</ul>
</li>
</ul>
`
期望的输出:
在点击任何东西之前(在初始化时):
在我点击一个 IBO (客户) 之后:
更新 1:
澄清我的意思:
The menu option is generated but not proccessed by the layout styles
如果,我的菜单组件初始化时没有 *ngIf
:
<li>
<a href="#">{{'IBO Details' | i18n}}</a>
<ul>
<li routerLinkActive="active" *ngFor="let navigatedIBO of navigationList">
<a href="#/ibos/IboDetails/{{navigatedIBO['id']}}">{{navigatedIBO['name']}}</a>
</li>
</ul>
</li>
然后布局样式可以根据这个结构生成菜单输出(见图片):
<li>
<a>
<ul>
<li *ngFor>
<a>
</li>
</ul>
</li>
因此添加 +
符号和子菜单行为等。
但是,如果它在没有所有元素的情况下进行初始化(当 *ngIf
是 false
时 <li>
并且它的子项未呈现,因此布局不考虑它们来绘制/创建菜单)和这些元素在渲染之后添加,那么它们将存在于源代码中,但我们将无法在菜单中看到它们,因为:
- 没有
+
创建 - 没有子菜单行为
最佳答案
Angular 有两种变化检测策略:
默认策略,自动检测模型中的变化并相应地重新渲染组件。
OnPush,只有在您明确告诉它这样做时才会重新呈现组件 所以。 另见 https://angular.io/docs/ts/latest/api/core/index/ChangeDetectionStrategy-enum.html
当您在一个页面上有多个元素或者当您希望对渲染过程有更多控制时,OnPush 策略可以有更好的性能。
为了使用这个策略,你必须在你的组件中声明它:
@Component({
selector: '[ibos-navigation-element]',
template: `...`,
changeDetection: ChangeDetectionStrategy.OnPush
})
然后注入(inject)你的构造函数:
constructor(
private changeDetector: ChangeDetectorRef,
) {}
当你想触发变化检测以便组件可以重新渲染时 (在你的例子中,在新的 IBO/客户被添加到模型之后),调用:
this.changeDetector.markForCheck();
查看官方教程中的现场演示:http://plnkr.co/edit/GC512b?p=preview
如果问题与变化检测无关,而是与 CSS/SCSS 样式有关, 请记住,在 Angular 2 中,每个组件都有自己的一组 CSS 类,并且 它们不是由“ child ”元素“继承”的。他们完全孤立 从彼此。一种解决方案是创建全局 CSS/SCSS 样式。
关于 Angular 2 : rendering/reloading a component's template,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43395808/