首页 文章

Angular 2 @ViewChild无效 . 无法读取未定义的属性“ Headers ”

提问于
浏览
0

即使在使用@ViewChild导入后,我也无法访问组件的属性 . 下面是代码 .

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

<div class="text-center header h3">{{monitorTitle}}</div>

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';

}

错误:未捕获(在承诺中):TypeError:无法读取未定义的属性'title'TypeError:无法读取未定义的属性'title'

帮我解决这个错误 .

1 回答

  • 3

    您应该检查 AfterViewChecked 中的 @ViewChild 而不是 AfterViewInit . 您也可以捆绑 @angular/core 导入,如下所示: import { Component, ViewChild, AfterViewInit } from '@angular/core'; . 然后实现 AfterViewChecked 而不是实现 AfterViewInit .

    以下是它的外观:

    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;
        }
     }
    

    一个问题:这些是父组件还是其中一个组件是另一个组件的子组件?我问的原因是你可能想要研究一种在组件之间传递该变量的不同方法,因为这可以通过 @Input 或使用服务来存储和设置头变量来实现 . 我希望这可以提供一些帮助 .

    编辑:

    要回答您的评论,您应该创建一个这样的服务:

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class HeaderService {
    
      _title: string;
    
      constructor() { }
    
      set title(title) {
        this._title = title;
      }
      get title() {
        return this._title;
      }
    
    }
    

    然后在您的组件中导入服务和 getset 变量:

    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;
        }
     }
    

    您只需要确保使用 this.headerService.title = 'yourTitle'; 在其中一个组件中设置 Headers

    我只是不确定首先加载哪个组件 .

    你应该在这里查看Angular服务:https://angular.io/tutorial/toh-pt4

    另请查看Angular Component Interaction:https://angular.io/guide/component-interaction

    编辑#2:

    这是在您的服务中订阅该 Headers 的另一种方法:

    所以下面我创建了一个类型为字符串的 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();
      }
    
    }
    

    然后在你的 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;
        }
     }
    

    然后在 AdminComponent 中,每当单击该按钮时,调用 this.headerService.setNextTitle(title) ,然后将确认您在HeaderMonitorComponent中订阅的新 Headers 并替换当前的 monitorTitle 值 .

    只是另一种快速处理数据传递的方法 .

相关问题