我无法在以下情况下正确初始化@ViewChild
注释字段:
@ViewChild
带注释的字段在某些情况下会保留undefined
:
X
的父组件实现类型为XBase
的抽象基类,它有三个抽象字段X
类型的组件使用@ChildView
类型A
,B
和C
C
注释这些字段
XBase
反过来也扩展了X
,但使用了与A
不同的模板和选择器B
和X
的字段在类型C
@Component({
moduleId: module.id,
selector: 'drive-view'
templateUrl: './../../html/drive-view.html'
})
export class DriveViewComponent extends GridView<Drive>
{
@ViewChild(DriveGridComponent)
public grid: DriveGridComponent;
@ViewChild(DriveDetailsComponent)
public itemDetails: DriveDetailsComponent;
@ViewChild(DriveFilterModalComponent)
public filterModal: DriveFilterModalComponent;
@ViewChild(DriveMembersModalComponent)
public driveMembersModal: DriveMembersModalComponent;
}
export abstract class GridView<TEntity>
{
public abstract grid: Grid<TEntity>;
public abstract filterModal: IGridFilterModal;
public abstract itemDetails: IGridItemDetails<TEntity>;
}
export abstract class Grid<TEntity>
{
public abstract header: IGridHeader;
public abstract body: IGridBody<TEntity>;
}
@Component({
moduleId: module.id,
selector: '[drive-grid]',
templateUrl: './../../html/grid.html'
})
export class DriveGridComponent extends Grid<Drive>
{
@ViewChild(DriveGridHeaderComponent)
public header: DriveGridHeaderComponent;
@ViewChild(DriveGridBodyComponent)
public body: DriveGridBodyComponent;
}
@Component({
moduleId: module.id,
selector: 'thead [grid-header]',
templateUrl: './../../html/drive-grid-header.html'
})
export class DriveGridHeaderComponent implements IGridHeader
{
// nothing to see here...
}
@Component({
moduleId: module.id,
selector: 'tbody [grid-body]',
templateUrl: './../../html/drive-grid-body.html'
})
export class DriveGridBodyComponent implements IGridBody<Drive>
{
// nothing to see here...
}
@Component({
moduleId: module.id,
selector: '[drive-members-modal]',
templateUrl: './../../html/drive-members-modal.html'
})
export class DriveMembersModalComponent extends GridView<User>
{
@ViewChild(UserGridComponent)
public grid: UserGridComponent;
}
@Component({
moduleId: module.id,
selector: '[user-grid]',
templateUrl: './../../html/grid.html'
})
export class UserGridComponent extends Grid<User>
{
@ViewChild(UserGridHeaderComponent)
public header: UserGridHeaderComponent;
@ViewChild(UserGridBodyComponent)
public body: UserGridBodyComponent;
}
的字段保持未定义这是我的代码缩短版
UserGridHeaderComponent
UserGridBodyComponent
和Drive-
等同于<div class="row">
<div class="col-lg-12"
drive-filter-modal
(onFilterApplyButtonEmitter)="onFilterApplyButton()">
</div>
</div>
<div class="row">
<div class="col-lg-12"
drive-members-modal>
</div>
</div>
<div class="row" [hidden]="!grid.body?.items">
<div class="col-lg-12"
drive-grid
(onColumnHeaderToggledEmitter)="onColumnHeaderToggled($event)"
(onDetailsButtonEmitter)="onDetailsButton($event)">
</div>
</div>
<div class="row"
id="row-grid-item-details">
<div class="col-lg-12"
[@detailsSlideUpDown]="itemDetails.fadeInOutStatus">
<item-details (onOpenModalEmitter)="onDriveMembersButton()"></item-details>
</div>
</div>
组件。
以下是html模板的相关部分:
驱动-view.html
<div class="table-responsive">
<table class="grid table table-hover">
<thead grid-header (onColumnHeaderToggledEmitter)="onColumnHeaderToggled($event)"></thead>
<tbody grid-body (onDetailsButtonEmitter)="onDetailsButton($event)"
[ngClass]="{'fadeIn': body?.items, 'fadeOut': !body?.items}"
class="animated"></tbody>
</table>
</div>
grid.html
<div class="modal fade" id="drive-members-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Members of 'NAME'</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-lg-12"
user-grid
(onColumnHeaderToggledEmitter)="onColumnHeaderToggled($event)"
(onDetailsButtonEmitter)="onDetailsButton($event)">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
<span class="glyphicon glyphicon-chevron-left"></span> Back
</button>
</div>
</div>
</div>
</div>
</div>
驱动构件-modal.html
GridView<T>
因此,我尝试做的是在DriveMembersModalComponent
内重用DriveViewComponent
形状的DriveViewComponent
。当用户想要查看驱动器的成员时,它应该在弹出的引导模式中呈现类似的网格。
但driveMembersModal
@ViewChild(UserGridComponent)
public grid: UserGridComponent;
未完全初始化。其
@ViewChild(<reference>)
保持未定义。似乎角度无法在模板中找到匹配的元素。我尝试过不同的选择器而没有效果。我还尝试了#reference
语法,其中ElementRef
属性添加到元素中。然而,这给了我一个DriveMembersModalComponent
,我不知道如何处理。它似乎只是一个DOM参考,但不是一个角度组件。
修改
我已经从我的应用中创建了一个plunker示例:https://embed.plnkr.co/083a5AnkaiCG796adTkR/
按照以下说明重现错误:
C
,它对应于上面提到的组件grid
。 undefined
字段为DriveViewComponent
。打印在ngAfterViewInit()
&#39; {{1}} 答案 0 :(得分:3)
在将上面的示例分解为最小的代码之后,我找出了@ViewChild
保持未定义的原因:
虽然我错过了导入的模块的导出语句,但是Angular没有抛出任何错误。如果您没有为模板使用明确的html标记,就会发生这种情况。
您可以在短弹射器后观察此行为:
https://plnkr.co/edit/kPKSbPS86iJ1oVCA4WSj?p=preview
如果您取消注释src/module.ts
中的第26行,App
的{{1}}将会正确呈现。如果您将模板的@ViewChild
代码更改为<div>
,则只会出现错误。然后Angular将抱怨未知元素并要求您检查它是否是Angular组件。
答案 1 :(得分:1)
我也有类似的错误,但这只是因为我是菜鸟。事实证明,如果您尝试在组件的构造函数中访问 ViewChild
,它还不存在,并且是未定义的...
我将访问我的 ViewChild
的代码移到了 ngAfterViewInit
,它的作用就像一个魅力。
附言任何像 ngIf/ngFor 这样的离子指令似乎也不喜欢被绑定,我想这是有道理的,因为它们的存在无论如何都是依赖的。
答案 2 :(得分:-1)
在核心导入中添加ViewChild
import { Component, OnInit,ViewChild } from '@angular/core';