简体   繁体   English

@ViewChild 返回未定义

[英]@ViewChild returns undefined

For some reason my @ViewChild in my Angular 5 App does not work.出于某种原因,我的 Angular 5 应用程序中的 @ViewChild 无法正常工作。 I have defined it like this in my component:我在我的组件中这样定义它:

case-detail.component.html: case-detail.component.html:

<div class="inner-tab-content" #innerTabContent>
    <!-- // more content here -->
</div>

I have implemented @ViewChild in my controller (above the constructor) like this:我在我的 controller(构造函数上方)中实现了@ViewChild ,如下所示:

case-detail.component.ts案例详细信息.component.ts

@ViewChild('innerTabContent') tabContentElement: ElementRef;

And I want to access it here in the component: case-detail.component.ts我想在组件中访问它: case-detail.component.ts

ngAfterViewInit() {
    console.log("scroll top: " + this.tabContentElement.nativeElement);
}

I've implemented the AfterViewInit interface.我已经实现了AfterViewInit接口。 ngAfterViewInit() is called correctly. ngAfterViewInit() 被正确调用。 However, this.tabContentElement is always undefined .但是, this.tabContentElement始终是undefined

Any help is greatly appreciated:)任何帮助是极大的赞赏:)

ViewChild() works fine on latest plunker Angular version with the scenario you describe. ViewChild()在最新的 plunker Angular 版本上可以正常工作,并具有您描述的场景。

Demonstration in this plunker : https://plnkr.co /edit/KzWnkE5Hvp7NUow6YAxy 在这个 plunker 中演示: https ://plnkr.co /edit/KzWnkE5Hvp7NUow6YAxy

EDIT: Here is a replacement StackBlitz for the above Plunker: https://stackblitz.com/edit/angular-ivy-pzaglm编辑:这是上述Plunker的替代StackBlitz: https ://stackblitz.com/edit/angular-ivy-pzaglm

component :组件:

ngAfterViewInit() {
    console.log(this.testView); // correctly outputs the element in console, not undefined
}
  • Check that ElementRef and ViewChild are correctly imported from '@angular/core'检查 ElementRef 和 ViewChild 是否从“@angular/core”正确导入

  • Your element might simply not be there at the time of AfterViewInit (in case there is a *ngIf , for instance. (seems the case as per your comments)您的元素可能在 AfterViewInit 时根本不存在(例如,如果有*ngIf (根据您的评论似乎是这种情况)

In the latter case, you can use a wrapper element and ViewChildren , that emits some event when a new child element is added - more info on documentation here : https://angular.io/api/core/ViewChildren在后一种情况下,您可以使用包装元素和ViewChildren ,当添加新的子元素时会发出一些事件 - 有关文档的更多信息: https : //angular.io/api/core/ViewChildren

note that there might be some issue with native div as per this question : @ViewChildren does not get updated with dynamically added DOM elements , but this can be worked around by using a new component that wraps your div, for instance.请注意,根据此问题,本机div可能存在一些问题: @ViewChildren 不会使用动态添加的 DOM 元素进行更新,但这可以通过使用包装 div 的新组件来解决,例如。

EDIT编辑

Or you can also use a timeout to wait for the component to be rendered.或者你也可以使用超时来等待组件被渲染。 I must say that I find this solution 'dirty', but glad it works for you :)我必须说我觉得这个解决方案“很脏”,但很高兴它对你有用:)

However, even if you access to the child component in the AfterViewInit , sometimes the @ViewChild was still returning null .但是,即使您访问AfterViewInit的子组件,有时@ViewChild仍然返回null The problem can be caused by the *ngIf or other directive.该问题可能是由*ngIf或其他指令引起的。

The solution is to use the @ViewChildren instead of @ViewChild and subscribe the changes subscription that is executed when the component is ready.解决方案是使用@ViewChildren而不是@ViewChild并订阅在组件准备就绪时执行的changes订阅。

For example, if in the parent component ParentComponent you want to access the child component MyComponent .例如,如果您想在父组件ParentComponent中访问子组件MyComponent

import { Component, ViewChildren, AfterViewInit, QueryList } from '@angular/core';
import { MyComponent } from './mycomponent.component';

export class ParentComponent implements AfterViewInit
{
  //other code emitted for clarity

  @ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>;

  public ngAfterViewInit(): void
  {
    this.childrenComponent.changes.subscribe((comps: QueryList<MyComponent>) =>
    {
      // Now you can access to the child component
    });
  }
}

To get this to work consistently in my case, I replaced all occurrences of为了让它在我的情况下始终如一地工作,我替换了所有出现的

*ngIf="check"

with

[style.display]="check ? 'block' : 'none'"

Otherwise the ViewChild components that didn't exist when my view first loaded would potentially remain undefined.否则,在我的视图首次加载时不存在的 ViewChild 组件可能会保持未定义状态。

A different answer to this question would be sometimes, The child component is still not rendered, when you access it.这个问题的不同答案有时是,当您访问子组件时,它仍未呈现。 For me it was due to an *ngIf so that child component is still not there.对我来说,这是由于 *ngIf 导致子组件仍然不存在。 For an example,例如,

<div *ngIf="check">
   <app-child-item></app-child-item>
</div>

And in your parent .ts file you try to access childItem while check is set to false.在您的父 .ts 文件中,您尝试在 check 设置为 false 时访问 childItem。

Using timeout and setting static to false worked for me.使用超时并将 static 设置为 false 对我有用。

@ViewChild(GoogleMapComponent) _GoogleMap: GoogleMapComponent; //Static is false
        
//Now use setTimeout inside ngOnInit
ngOnInit(){
    setTimeout(() => {
      this._GoogleMap.$mapReady.subscribe((map) => {
        this.map = map;
        marker.setMap(map);
      });
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM