typescript Angular 2 @ViewChild 不工作。无法读取未定义的属性“标题”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47559141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 2 @ViewChild not working. Cannot Read Property "title" of Undefined
提问by Dheeraj Naik
I am unable to access the property of component even after importing with @ViewChild. Below is the code.
即使使用@ViewChild 导入后,我也无法访问组件的属性。下面是代码。
header.monitor.component.ts
header.monitor.component.ts
import { AdminComponent } from 'admin/admin.component';
import { Component } from '@angular/core';
import { ViewChild, AfterViewInit } from '@angular/core';
@Component({
selector: 'monitor-header',
templateUrl: './header.monitor.component.html',
styleUrls: ['./header.monitor.component.css']
})
export class HeaderMonitorComponent implements AfterViewInit {
@ViewChild(AdminComponent) private admin: AdminComponent;
private monitorTitle: string;
ngAfterViewInit() {
this.monitorTitle = this.admin.title;
}
}
header.monitor.component.html
header.monitor.component.html
<div class="text-center header h3">{{monitorTitle}}</div>
admin.component.ts
admin.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { ElementRef } from '@angular/core';
@Component({
selector: 'monitor-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css']
})
export class AdminComponent {
constructor() { }
title = 'Header';
}
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'title' of undefined TypeError: Cannot read property 'title' of undefined
错误错误:未捕获(承诺):类型错误:无法读取未定义的属性“标题”类型错误:无法读取未定义的属性“标题”
Help me resolve this error.
帮我解决这个错误。
回答by Nicholas Pesa
You should be checking for the @ViewChild
in the AfterViewChecked
instead of the AfterViewInit
. Also you can bundle your @angular/core
imports like so:
import { Component, ViewChild, AfterViewInit } from '@angular/core';
. Then instead of implementing AfterViewInit
just implement AfterViewChecked
.
您应该检查@ViewChild
inAfterViewChecked
而不是AfterViewInit
。你也可以捆绑你的@angular/core
进口,像这样:
import { Component, ViewChild, AfterViewInit } from '@angular/core';
。然后,而不是实施AfterViewInit
只是实施AfterViewChecked
。
Here is how it could look:
这是它的外观:
import { AdminComponent } from 'admin/admin.component';
import { Component, ViewChild, AfterViewChecked } from '@angular/core';
@Component({
selector: 'monitor-header',
templateUrl: './header.monitor.component.html',
styleUrls: ['./header.monitor.component.css']
})
export class HeaderMonitorComponent implements AfterViewChecked {
@ViewChild(AdminComponent) private admin: AdminComponent;
private monitorTitle: string;
ngAfterViewChecked() {
this.monitorTitle = this.admin.title;
}
}
One question: Are these both parent components or will one of the components be a child of the other? The reason i ask is that you may want to look into a different method of passing that variable between components as this may be achieved with an @Input
or using a service to store and set the header variable. I hope this can be of some help.
一个问题:这些都是父组件还是其中一个组件是另一个组件的子组件?我问的原因是您可能想要研究在组件之间传递该变量的不同方法,因为这可以通过使用@Input
或使用服务来存储和设置标头变量来实现。我希望这能有所帮助。
EDIT:
编辑:
To answer your comment, you should create a service like this:
要回答您的评论,您应该创建一个这样的服务:
import { Injectable } from '@angular/core';
@Injectable()
export class HeaderService {
_title: string;
constructor() { }
set title(title) {
this._title = title;
}
get title() {
return this._title;
}
}
Then in your component import the service and get
or set
the variable:
然后在您的组件中导入服务和/get
或set
变量:
import { AdminComponent } from 'admin/admin.component';
import { Component, ViewChild, AfterViewChecked } from '@angular/core';
import { HeaderService } from 'path/to/your/service';
@Component({
selector: 'monitor-header',
templateUrl: './header.monitor.component.html',
styleUrls: ['./header.monitor.component.css']
})
export class HeaderMonitorComponent implements AfterViewChecked {
@ViewChild(AdminComponent) private admin: AdminComponent;
private monitorTitle: string;
constructor(private headerService: HeaderService) {} // Import service here
ngAfterViewChecked() {
this.monitorTitle = this.headerService.title;
}
}
You just need to make sure you set the title in one of the components using this.headerService.title = 'yourTitle';
您只需要确保使用以下组件在其中一个组件中设置标题 this.headerService.title = 'yourTitle';
I am just not sure which component gets loaded first.
我只是不确定首先加载哪个组件。
You should check out Angular Services here: https://angular.io/tutorial/toh-pt4
您应该在此处查看 Angular 服务:https: //angular.io/tutorial/toh-pt4
Also check out Angular Component Interaction here: https://angular.io/guide/component-interaction
还可以在此处查看 Angular 组件交互:https: //angular.io/guide/component-interaction
EDIT #2:
编辑#2:
Here is another way to subscribe to that title in your Service:
这是在您的服务中订阅该标题的另一种方法:
So here below I have created a Subject
that is of type string, and a method that tells it here is the next string to hold and send.
所以在下面我创建了一个Subject
字符串类型,一个方法告诉它是下一个要保存和发送的字符串。
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class HeaderService {
public titleSubject: Subject<string> = new Subject<string>();
constructor() { }
setNextTitle(title) {
this.titleSubject.next();
}
}
Then in your HeaderMonitorComponent
you would want to subscribe to that Subject
like so:
然后在你HeaderMonitorComponent
想要订阅Subject
这样的:
import { AdminComponent } from 'admin/admin.component';
import { Component, OnInit ViewChild, AfterViewChecked } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HeaderService } from 'path/to/your/service';
@Component({
selector: 'monitor-header',
templateUrl: './header.monitor.component.html',
styleUrls: ['./header.monitor.component.css']
})
export class HeaderMonitorComponent implements OnInit, AfterViewChecked {
@ViewChild(AdminComponent) private admin: AdminComponent;
private monitorTitle: string;
titleObservable: Observable<string>;
constructor(private headerService: HeaderService) {} // Import service here
ngOnInit() {
this.titleObservable = this.headerService.titleSubject.asObservable();
this.titleObservable.subscribe((title) => {
this.monitorTitle = title;
});
}
ngAfterViewChecked() {
this.monitorTitle = this.headerService.title;
}
}
Then in your AdminComponent
, whenever the button is clicked, call this.headerService.setNextTitle(title)
and the new title which you are subscribing to in the HeaderMonitorComponent will then be acknowledged and replace the current value of monitorTitle
.
然后在您的 中AdminComponent
,无论何时单击按钮,都会调用this.headerService.setNextTitle(title)
您在 HeaderMonitorComponent 中订阅的新标题,然后将确认并替换 的当前值monitorTitle
。
Just another quick way to handle the data passing through.
处理传递的数据的另一种快速方法。