【问题标题】:Angular 8 viewChild returns undefinedAngular 8 viewChild 返回未定义
【发布时间】:2019-10-19 11:12:25
【问题描述】:

我正在尝试访问 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 is undefined"。

它正在使用 Angular 7。

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

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

就我而言,这两个选项都不起作用。

【问题讨论】:

  • stackblitz 上的演示会很棒。
  • 你的html代码在哪里?
  • 尝试删除读取选项
  • 我尝试删除读取标志,但没有帮助。

标签: javascript angular web angular8


【解决方案1】:

根据docs,元数据属性read为:

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

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

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

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,即在 onInit() 方法中未定义 ViewChild 组件。

    This fixed the issue:

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

    【讨论】:

    • 我也解决了!
    【解决方案3】:

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

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      但是,我正在实现一个事件订阅,以使用this.action()withing 事件在子节点上触发一个方法,该事件通过事件丢失了它的引用。 (我这边的事件很糟糕)

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

      var self = this; // var because we want it to stick around. 
      
      subscription.event.subscribe(()=>{
       self.callOnThisRef();
      }) 
      

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

      【讨论】:

        【解决方案5】:

        对于 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');
                        });
                }
            }
        

        【讨论】:

          【解决方案6】:

          我花了一个小时在 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>
          

          但我改为使用 new-task 选择器。

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

          【讨论】:

            【解决方案7】:

            在我的情况下,我让我的孩子处于 *ngIf 条件。因此 ViewChild 无法初始化所需的元素。更新了在 *ngIf 之外渲染组件的逻辑,ViewChild 能够成功地初始化元素。

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

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

                【解决方案9】:

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

                【讨论】:

                • 模板: ngAfterViewChecked: const el: HTMLTableElement = this.test.nativeElement;对我来说,上面的测试不起作用 el 是未定义的,有人知道为什么吗?
                【解决方案10】:

                我遇到了错误,但导致的原因更隐蔽。 Simply My View Child 组件在模板上出现错误,其中未定义变量。我只是因为我修改了 HTML 而感知到了它。一旦没有触发错误消息,就很难注意到错误。

                【讨论】:

                  【解决方案11】:

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

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

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

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

                  【讨论】:

                    猜你喜欢
                    • 2020-03-25
                    • 2017-01-08
                    • 2019-07-28
                    • 2023-03-05
                    • 2016-04-29
                    • 2017-03-11
                    • 2023-03-21
                    • 2019-10-03
                    相关资源
                    最近更新 更多