And*_*nti 203 typescript angular
我正在努力学习Angular 2.
我想使用@ViewChild Annotation 从父组件访问子组件.
这里有一些代码行:
在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);
}
}
Run Code Online (Sandbox Code Playgroud)
而在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(){};
}
Run Code Online (Sandbox Code Playgroud)
最后这里是模板(如评论中所示):
BodyContent.html
<div (click)="onClickSidebar()" class="row" style="height:200px; background-color:red;">
<ico-filter-tiles></ico-filter-tiles>
</div>
Run Code Online (Sandbox Code Playgroud)
FilterTiles.html
<h1>Tiles loaded</h1>
<div *ngFor="#tile of tiles" class="col-md-4">
... stuff ...
</div>
Run Code Online (Sandbox Code Playgroud)
FilterTiles.html模板正确加载到 ico-filter-tiles标记中(实际上我能够看到标题).
注意:BodyContent类使用DynamicComponetLoader注入另一个模板(Body):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);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我尝试写入ft控制台日志时,我得到了undefined,当我尝试在"tiles"数组中推送一些内容时,我当然会遇到异常:'没有属性区块为"undefined"'.
还有一件事:FilterTiles组件似乎正确加载,因为我能够看到它的html模板.
有什么建议吗?谢谢
ken*_*ell 312
我有一个类似的问题,并认为我发布以防其他人犯了同样的错误.首先,要考虑的一件事是AfterViewInit; 您需要等待视图初始化才能访问您的视图@ViewChild.但是,我@ViewChild仍然返回null.问题是我的*ngIf.该*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
}
}
Run Code Online (Sandbox Code Playgroud)
希望有所帮助.
编辑
正如下面@Ashg所提到的,解决方案是使用@ViewChildren而不是@ViewChild.
Ash*_*shg 115
前面提到的问题是导致视图未定义的ngIf.答案是使用ViewChildren而不是ViewChild.我有类似的问题,我不希望在加载所有参考数据之前显示网格.
HTML:
<section class="well" *ngIf="LookupData != null">
<h4 class="ra-well-title">Results</h4>
<kendo-grid #searchGrid> </kendo-grid>
</section>
Run Code Online (Sandbox Code Playgroud)
组件代码
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;
});
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们使用ViewChildren来监听更改.在这种情况下,任何带有#searchGrid引用的子代.希望这可以帮助.
par*_*ent 59
你可以使用一个setter @ViewChild()
@ViewChild(FilterTiles) set ft(tiles: FilterTiles) {
console.log(tiles);
};
Run Code Online (Sandbox Code Playgroud)
如果你有一个ngIf包装器,将使用undefined调用setter,然后在ngIf允许它渲染时再使用引用.
我的问题是其他问题.我没有在我的app.modules中包含包含我的"FilterTiles"的模块.模板没有抛出错误,但引用始终未定义.
Pau*_*eau 44
解决我的问题的是确保static设置为false.
@ViewChild(ClrForm, {static: false}) clrForm;
Run Code Online (Sandbox Code Playgroud)
随着static关闭,@ViewChild参考得到由角时更新的*ngIf指令改变。
Jos*_*yck 23
这对我有用.
例如,名为"my-component"的组件使用*ngIf ="showMe"显示,如下所示:
<my-component [showMe]="showMe" *ngIf="showMe"></my-component>
Run Code Online (Sandbox Code Playgroud)
因此,当组件初始化时,组件尚未显示,直到"showMe"为真.因此,我的@ViewChild引用都是未定义的.
这是我使用@ViewChildren和它返回的QueryList的地方.请参阅QueryList上的角度文章和@ViewChildren用法演示.
您可以使用@ViewChildren返回的QueryList,并使用rxjs订阅对引用项的任何更改,如下所示.@ViewChid没有这种能力.
import { Component, ViewChildren, ElementRef, OnChanges, QueryList, Input } from '@angular/core';
import 'rxjs/Rx';
@Component({
selector: 'my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnChanges {
@ViewChildren('ref') ref: QueryList<any>; // this reference is just pointing to a template reference variable in the component html file (i.e. <div #ref></div> )
@Input() showMe; // this is passed into my component from the parent as a
ngOnChanges () { // ngOnChanges is a component LifeCycle Hook that should run the following code when there is a change to the components view (like when the child elements appear in the DOM for example)
if(showMe) // this if statement checks to see if the component has appeared becuase ngOnChanges may fire for other reasons
this.ref.changes.subscribe( // subscribe to any changes to the ref which should change from undefined to an actual value once showMe is switched to true (which triggers *ngIf to show the component)
(result) => {
// console.log(result.first['_results'][0].nativeElement);
console.log(result.first.nativeElement);
// Do Stuff with referenced element here...
}
); // end subscribe
} // end if
} // end onChanges
} // end Class
Run Code Online (Sandbox Code Playgroud)
希望这有助于节省一些时间和挫折.
小智 8
我的解决方法是使用[style.display] ="getControlsOnStyleDisplay()"而不是*ngIf ="controlsOn".块在那里,但不显示.
@Component({
selector: 'app',
template: `
<controls [style.display]="getControlsOnStyleDisplay()"></controls>
...
export class AppComponent {
@ViewChild(ControlsComponent) controls:ControlsComponent;
controlsOn:boolean = false;
getControlsOnStyleDisplay() {
if(this.controlsOn) {
return "block";
} else {
return "none";
}
}
....
Run Code Online (Sandbox Code Playgroud)
在我的例子中,我有一个使用ViewChild,的输入变量 setter ,并且在指令ViewChild内部*ngIf,所以 setter 试图在*ngIf渲染之前访问它(没有*ngIf,它可以正常工作,但如果它总是设置为真*ngIf="true")。
为了解决这个问题,我使用 Rxjs 来确保ViewChild在视图启动之前对等待的任何引用。首先,创建一个在 view init 之后完成的主题。
export class MyComponent implements AfterViewInit {
private _viewInitWaiter$ = new Subject();
ngAfterViewInit(): void {
this._viewInitWaiter$.complete();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,创建一个在主题完成后接受并执行 lambda 的函数。
private _executeAfterViewInit(func: () => any): any {
this._viewInitWaiter$.subscribe(null, null, () => {
return func();
})
}
Run Code Online (Sandbox Code Playgroud)
最后,确保对 ViewChild 的引用使用此函数。
@Input()
set myInput(val: any) {
this._executeAfterViewInit(() => {
const viewChildProperty = this.viewChild.someProperty;
...
});
}
@ViewChild('viewChildRefName', {read: MyViewChildComponent}) viewChild: MyViewChildComponent;
Run Code Online (Sandbox Code Playgroud)
它必须有效。
\n\n但正如G\xc3\xbcnter Z\xc3\xb6chbauer所说,模板中肯定还有其他问题。我创建了一种Relevant-Plunkr-Answer。请检查浏览器的控制台。
\n\n启动.ts
\n\n@Component({\nselector: \'my-app\'\n, template: `<div> <h1> BodyContent </h1></div>\n\n <filter></filter>\n\n <button (click)="onClickSidebar()">Click Me</button>\n `\n, directives: [FilterTiles] \n})\n\n\nexport class BodyContent {\n @ViewChild(FilterTiles) ft:FilterTiles;\n\n public onClickSidebar() {\n console.log(this.ft);\n\n this.ft.tiles.push("entered");\n } \n}\nRun Code Online (Sandbox Code Playgroud)\n\n过滤器Tiles.ts
\n\n@Component({\n selector: \'filter\',\n template: \'<div> <h4>Filter tiles </h4></div>\'\n })\n\n\n export class FilterTiles {\n public tiles = [];\n\n public constructor(){};\n }\nRun Code Online (Sandbox Code Playgroud)\n\n它就像一个魅力。请仔细检查您的标签和参考文献。
\n\n谢谢...
\n对我来说,使用ngAfterViewInit而不是ngOnInit解决问题:
export class AppComponent implements OnInit {
@ViewChild('video') video;
ngOnInit(){
// <-- in here video is undefined
}
public ngAfterViewInit()
{
console.log(this.video.nativeElement) // <-- you can access it here
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
169251 次 |
| 最近记录: |