我正在尝试学习 Angular 2。
我想使用 @ViewChild 注解从父组件访问子组件。
这里有几行代码:
在 _ BodyContent.ts_ 我有:
import { ViewChild, Component, Injectable } from 'angular2/core'; import { FilterTiles } from '../Components/FilterTiles/FilterTiles'; @Component({ selector: 'ico-body-content', templateUrl: 'App/Pages/Filters/BodyContent/BodyContent.html', directives: [FilterTiles] }) export class BodyContent { @ViewChild(FilterTiles) ft: FilterTiles; public onClickSidebar(clickedElement: string) { console.log(this.ft); var startingFilter = { title: 'cognomi', values: [ 'griffin', 'simpson' ] } this.ft.tiles.push(startingFilter); } }
在 _ FilterTiles.ts_ 中:
import { Component } from 'angular2/core'; @Component({ selector: 'ico-filter-tiles', templateUrl: 'App/Pages/Filters/Components/FilterTiles/FilterTiles.html' }) export class FilterTiles { public tiles = []; public constructor(){}; }
最后是模板(如评论中所建议):
正文内容.html
<div (click)="onClickSidebar()" class="row" style="height:200px; background-color:red;"> <ico-filter-tiles></ico-filter-tiles> </div>
FilterTiles.html
<h1>Tiles loaded</h1> <div *ngFor="#tile of tiles" class="col-md-4"> ... stuff ... </div>
FilterTiles.html 模板已正确加载到 ico-filter-tiles 标记中(确实我能够看到标题)。
注意:BodyContent该类被注入到另一个模板(Body)中,使用DynamicComponetLoader: dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector):
BodyContent
DynamicComponetLoader: dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector)
import { ViewChild, Component, DynamicComponentLoader, Injector } from 'angular2/core'; import { Body } from '../../Layout/Dashboard/Body/Body'; import { BodyContent } from './BodyContent/BodyContent'; @Component({ selector: 'filters', templateUrl: 'App/Pages/Filters/Filters.html', directives: [Body, Sidebar, Navbar] }) export class Filters { constructor(dcl: DynamicComponentLoader, injector: Injector) { dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector); dcl.loadAsRoot(SidebarContent, '#ico-sidebarContent', injector); } }
问题是,当我尝试写入ft控制台日志时,我得到undefined了,当然,当我尝试在“tiles”数组中推送一些东西时,我得到一个异常: ‘no property tiles for “undefined”’ 。
ft
undefined
还有一件事:FilterTiles组件似乎已正确加载,因为我能够看到它的 html 模板。
FilterTiles
有什么建议?
我有一个类似的问题,并认为我会发布以防其他人犯同样的错误。首先,要考虑的一件事是AfterViewInit;您需要等待视图初始化,然后才能访问您的@ViewChild. 但是,我@ViewChild的仍然返回 null。问题是我的*ngIf. 该*ngIf指令正在杀死我的控件组件,因此我无法引用它。
AfterViewInit
@ViewChild
*ngIf
import { Component, ViewChild, OnInit, AfterViewInit } from 'angular2/core'; import { ControlsComponent } from './controls/controls.component'; import { SlideshowComponent } from './slideshow/slideshow.component'; @Component({ selector: 'app', template: ` <controls *ngIf="controlsOn"></controls> <slideshow (mousemove)="onMouseMove()"></slideshow> `, directives: [SlideshowComponent, ControlsComponent], }) export class AppComponent { @ViewChild(ControlsComponent) controls: ControlsComponent; controlsOn: boolean = false; ngOnInit() { console.log('on init', this.controls); // this returns undefined } ngAfterViewInit() { console.log('on after view init', this.controls); // this returns null } onMouseMove(event) { this.controls.show(); // throws an error because controls is null } }
希望有帮助。
编辑 正如下面所提到的,一个解决方案是使用@ViewChildren而不是@ViewChild.
@ViewChildren
前面提到的问题ngIf是导致视图未定义的问题。答案是使用ViewChildren而不是ViewChild. 我有类似的问题,我不希望在加载所有参考数据之前显示网格。
ngIf
ViewChildren
ViewChild
html:
<section class="well" *ngIf="LookupData != null"> <h4 class="ra-well-title">Results</h4> <kendo-grid #searchGrid> </kendo-grid> </section>
组件代码
import { Component, ViewChildren, OnInit, AfterViewInit, QueryList } from '@angular/core'; import { GridComponent } from '@progress/kendo-angular-grid'; export class SearchComponent implements OnInit, AfterViewInit { //other code emitted for clarity @ViewChildren("searchGrid") public Grids: QueryList<GridComponent> private SearchGrid: GridComponent public ngAfterViewInit(): void { this.Grids.changes.subscribe((comps: QueryList <GridComponent>) => { this.SearchGrid = comps.first; }); } }
在这里,我们正在使用ViewChildren它来监听变化。在这种情况下,任何孩子都可以参考#searchGrid。希望这可以帮助。
#searchGrid