繁体   English   中英

Angular 8 viewChild 返回未定义

[英]Angular 8 viewChild returns undefined

我正在尝试访问 childView 实例,但它一直说 childView 未定义。

这是我的 childViews 代码:

@ViewChild(CreateQuestionnaireComponent,{ read: true, static: false })  private childQuestionnaireDialog:CreateQuestionnaireComponent;
@ViewChild(ProjectNavbarComponent,{ read: true, static: false })  private childProjectNavBar:ProjectNavbarComponent;
@ViewChild(QuestionnaireNodeComponent,{ read: true, static: false }) private childQuestionnaireNode:QuestionnaireNodeComponent;
....

onCreateTerminal() {
        this.childQuestionnaireDialog.generateQuestionnaireDropDownList();
        this.childQuestionnaireDialog.resetFields();
        this._hideQuestionnaireDialog = false;
        this._modalTitle = 'New Terminal';
        this._placeHolderText = 'Terminal Questionnaire Title';
        this._terminal = true;
    }

...

它说:this.childQuestionnaireDialog 未定义”。

它正在与 Angular 7 一起工作。

根据我的新知识,@viewChild 带有一个名为 static 的标志。如果我们将该标志设置为 true,则父组件会在其自己的创建过程中尝试获取对 childView 的引用。 换句话说,我们可以在父组件的 onInit() 方法中有一个 childView 的实例。基本上是一次性访问,因为我们将无法在任何其他方法中访问。

标志设置为 false,基本上是 ivy 渲染器中的新方法。

我的问题是,这两个选项都不起作用。

我有一个类似的问题,其中 ViewChild 组件在 onInit() 方法中未定义。

这解决了这个问题

// Ensure Change Detection runs before accessing the instance
@ContentChild('foo', { static: false }) foo!: ElementRef;

// If you need to access it in ngOnInit hook
@ViewChild(TemplateRef, { static: true }) foo!: TemplateRef;

您必须在视图完成初始化之前尝试访问 ViewChild 查询的结果。

因此,您可以将查询标记为静态:

@ViewChild('test', {static: true}) test: ElementRef;

...或将逻辑移至 ngAfterViewInit (首选)。

参考https://angular.io/guide/static-query-migration

我花了一个小时没有在 SO 上找到它,所以它也可以帮助其他人:我的错误是我在 angular html 中使用了错误的选择器。 我想引用的组件如下所示:

@Component({
  selector: 'app-universal-modal',
  templateUrl: './universal-modal.component.html',
  styleUrls: ['./universal-modal.component.scss']
})
export class UniversalModalComponent implements OnInit {

现在我在其父级中使用了 viewchild:

  @ViewChild('universalModalComponent', {static: true}) universalModalComponent: UniversalModalComponent;

并且 html 选择器应该是app-universal-modal

  <app-universal-modal #universalModalComponent ></app-universal-modal>

但是我使用了新任务选择器。

奇怪的是没有编译时错误,而是运行时错误......

就我而言,我让我的孩子处于 *ngIf 状态。 因此 ViewChild 无法初始化所需的元素。 更新了在 *ngIf 之外渲染组件的逻辑,因此 ViewChild 能够成功初始化元素。

因此,如果可能,当需要 ViewChild 时,更改逻辑以在 *ngIf 之外呈现组件并显示适当的消息。 或者使用 CSS 隐藏元素的可见性,而不是使用 *ngIf。

如果您在 .HTML 文件中的*ngIf条件中使用 #viewchildTemplateRef 元素,则 .ts 文件中的 @ViewChild 选择器/引用变量将是未定义的。 因此,请改用[ngClass]

示例:使用[ngClass]={'hide': data.length = 0}而不是*ngIf=data.length>0

根据docs读取的元数据属性是:

`read - read a different token from the queried elements.`

换句话说,如果您想读取ViewContainerRef或 Component 名称而不是普通的ElementRef (如果您不read ,这是默认值),则使用它。 因此,将true作为值表示从元素返回true类型,据我所知这是不可能的。

更好的解释是here ,但对您的问题的简短回答是取出read属性或指定ElementRef或您想要的特定类型。

我这边的问题略有不同,因此为后代添加。

我最初是在实现一个@ViewChild并且在组件的范围内一切正常。

但是,我正在实现一个事件订阅,以在事件中使用this.action()this.action()孩子的方法,该事件通过事件丢失了它的引用。 (我这边的不良事件)

对我来说很奇怪,但一种解决方案(不是最佳解决方案,但在事件管理器重构之前)是在订阅创建时传递对此的引用。

var self = this; // var because we want it to stick around. 

subscription.event.subscribe(()=>{
 self.callOnThisRef();
}) 

我确信这是设计使然,因为它突出了我的活动管理问题。 但是调试起来很奇怪。

对于 Angular 7,我们不会得到{static: boolean}参数,而是得到{read: any}在我的情况下,我有一个*ngif指令,所以元素的引用不是通过 Viewchild() 获取的,我所做的我刚刚检查了 Component.ts 中的元素是否未定义


如果你需要在 ngOnInit 钩子中访问它

这是通过热听删除类的示例

@ViewChild('elref', ) elref: ElementRef;

import { Component, ElementRef, , Renderer2, ViewChild } from'@angular/core';

export class Component implements OnInit {
 @ViewChild('elref', ) elref: ElementRef;
    constructor(private renderer: Renderer2) {}
     ngOnInit() { this.hotlistening(); }
      hotlistening() {
        this.renderer.listen('window', 'click', (e: Event) => {
                if (this.elref !== undefined) { //Here i checked for undefined
                    this.elref.nativeElement.classList.remove('open');
                });
        }
    }

@ViewChild('test', {static: false}) 测试:ElementRef;

我有错误,但造成的更隐蔽。 只是我的视图子组件在模板上有一个错误,其中一个变量未定义。 我只是因为我修改了 HTML 才感觉到它。 一旦没有触发错误消息,就很难注意到错误。

(我知道这个问题有点老了。但对于那些仍然像我一样发现提示的人)

我也遇到过这个问题,我发现当您的元素位于具有*ngIf的父元素时, {static: true}选项可能无法始终正常工作。

我的解决方法是将该元素设为子组件并在其自己的 ngOnInit 或 ngAfterViewInit 上使用它。 这样,我就不用去检查它是否真的存在,订阅更改,或者一些复杂的额外工作。

也许你也可以考虑一下。 如果可能,我认为这是最简单的解决方案。

让孩子在ngOnInit()中可用

@ViewChild(CreateQuestionnaireComponent,{ read: true, static: false }) private childQuestionnaireDialog:CreateQuestionnaireComponent;

让孩子在ngAfterViewInit()中可用

@ViewChild(CreateQuestionnaireComponent,{ read: true, static: false }) private childQuestionnaireDialog:CreateQuestionnaireComponent;

但请确保您的父组件 html 中的子组件<app-questionnaire> </app-questionnaire>的选择器不应嵌入任何条件,否则它不会遵循上述模式,它将要求条件先为真。

暂无
暂无

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

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