Angular 2 @ViewChild 注释返回未定义 [英] Angular 2 @ViewChild annotation returns undefined
问题描述
我正在尝试学习 Angular 2.
我想使用 @ViewChild 注释从父组件访问子组件.
这里有几行代码:
在BodyContent.ts中,我有:
import { ViewChild, Component, Injectable } from 'angular2/core';从'../Components/FilterTiles/FilterTiles'导入{FilterTiles};@成分({选择器:'ico-body-content',templateUrl: 'App/Pages/Filters/BodyContent/BodyContent.html',指令:[FilterTiles]})导出类 BodyContent {@ViewChild(FilterTiles) ft: FilterTiles;公共 onClickSidebar(clickedElement: string) {控制台日志(this.ft);var 起始过滤器 = {标题:'认知',值:['格里芬','辛普森']}this.ft.tiles.push(startingFilter);}}
在FilterTiles.ts中:
import { Component } from 'angular2/core';@成分({选择器:'ico-filter-tiles',templateUrl: 'App/Pages/Filters/Components/FilterTiles/FilterTiles.html'})导出类 FilterTiles {公共瓷砖 = [];公共构造函数(){};}
最后是模板(如评论中所建议):
BodyContent.html
FilterTiles.html
<h1>已加载瓷砖</h1><div *ngFor="#tile oftiles";class=col-md-4">... 东西 ...
FilterTiles.html 模板已正确加载到 ico-filter-tiles 标记中(确实我能够看到标题).
注意:BodyContent
类使用 DynamicComponetLoader: dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector)
:
import { ViewChild, Component, DynamicComponentLoader, Injector } from 'angular2/core';从'../../Layout/Dashboard/Body/Body'导入{正文};从'./BodyContent/BodyContent'导入{BodyContent};@成分({选择器:'过滤器',templateUrl: 'App/Pages/Filters/Filters.html',指令:[正文、侧边栏、导航栏]})导出类过滤器{构造函数(dcl:DynamicComponentLoader,注入器:注入器){dcl.loadAsRoot(BodyContent, '#ico-bodyContent', 注入器);dcl.loadAsRoot(SidebarContent, '#ico-sidebarContent', 注入器);}}
问题是,当我尝试将 ft
写入控制台日志时,我得到 undefined
,当然当我尝试将某些内容推送到其中时会出现异常瓷砖"数组:'没有未定义"的属性图块'.
还有一件事:FilterTiles
组件似乎已正确加载,因为我能够看到它的 html 模板.
有什么建议吗?
我遇到了类似的问题,我想我会发帖以防其他人犯同样的错误.首先,要考虑的一件事是 AfterViewInit
;您需要等待视图初始化,然后才能访问您的 @ViewChild
.但是,我的 @ViewChild
仍然返回 null.问题是我的 *ngIf
.*ngIf
指令正在杀死我的控件组件,因此我无法引用它.
import {Component, ViewChild, OnInit, AfterViewInit} from 'angular2/core';从'./controls/controls.component'导入{ControlsComponent};从'./slideshow/slideshow.component'导入{SlideshowComponent};@成分({选择器:'应用',模板:`<controls *ngIf="controlsOn"></controls><幻灯片(mousemove)="onMouseMove()"></slideshow>`,指令:[SlideshowComponent, ControlsComponent]})导出类 AppComponent {@ViewChild(ControlsComponent) 控件:ControlsComponent;controlOn:boolean = false;ngOnInit() {console.log('on init', this.controls);//这将返回未定义}ngAfterViewInit() {console.log('on after view init', this.controls);//这将返回 null}onMouseMove(事件){this.controls.show();//抛出错误,因为控件为空}}
希望有所帮助.
编辑
正如 @Ashg 下面 所述,解决方案是使用 @ViewChildren
而不是 @ViewChild
.
I am trying to learn Angular 2.
I would like to access to a child component from a parent component using the @ViewChild Annotation.
Here some lines of code:
In BodyContent.ts I have:
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);
}
}
while in 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(){};
}
Finally here the templates (as suggested in comments):
BodyContent.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 template is correctly loaded into ico-filter-tiles tag (indeed I am able to see the header).
Note: the BodyContent
class is injected inside another template (Body) using 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);
}
}
The problem is that when I try to write ft
into the console log, I get undefined
, and of course I get an exception when I try to push something inside the "tiles" array: 'no property tiles for "undefined"'.
One more thing: FilterTiles
component seems to be correctly loaded, since I'm able to see the html template for it.
Any suggestions?
I had a similar issue and thought I'd post in case someone else made the same mistake. First, one thing to consider is AfterViewInit
; you need to wait for the view to be initialized before you can access your @ViewChild
. However, my @ViewChild
was still returning null. The problem was my *ngIf
. The *ngIf
directive was killing my controls component so I couldn't reference it.
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
}
}
Hope that helps.
EDIT
As mentioned by @Ashg below, a solution is to use @ViewChildren
instead of @ViewChild
.
这篇关于Angular 2 @ViewChild 注释返回未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!