Angular 2 @ViewChild返回undefined

我查看了几个相关的帖子和文档,但仍然无法从@ViewChild获得预期的行为 .

最终,我正在尝试设置div的滚动位置 . 此元素不是组件,而是HTML中的普通div .

为了实现这一点,我试图使用@ViewChild来获取我需要的DOM元素,并设置其滚动值 . (顺便说一句,如果你知道一个更好的方法来实现这个没有@ViewChild(或jQuery),将非常感谢答案!)

目前,@ ViewChild只返回undefined . 经历一些虚拟检查: - 我在AfterViewInit中访问我的元素 - 我没有任何其他指令,如* ngIf或* ngFor在这个元素上 .

这是控制器:

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

@Component({
    selector: 'portfolio-page',
    templateUrl: './portfolio-page.component.html',
    styleUrls: ['./portfolio-page.component.scss']
})

export class PortfolioPageComponent implements AfterViewInit{
    @ViewChild('gallery-container') galleryContainer: ElementRef;

    ngAfterViewInit(){
        console.log('My element: ' + this.galleryContainer);
    }
}

和模板:

<div id='gallery-container' class='gallery-image-container'>
    <div class='gallery-padding'></div>
    <img class='gallery-image' src='{{ coverPhotoVm }}' />
    <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>

我的输出很简单:我的元素:未定义 .

如您所见,我目前正在尝试按ID访问元素,但也尝试过类名 . 任何人都可以提供有关ViewChild选择器查询期望的更多详细信息吗?

我还看到了一个示例,其中散列'#'用作@ViewChild使用的选择器标识符 - 但是这会导致我使用#gallery-container导致模板解析错误 .

我想不出任何可能在这里错误的事情 . 感谢所有帮助,谢谢!

完整代码可在此处获取:https://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page

回答(3)

3 years ago

尝试在模板中使用ref:

<div id='gallery-container' #galleryContainer class='gallery-image-container'>
    <div class='gallery-padding'></div>
    <img class='gallery-image' src='{{ coverPhotoVm }}' />
    <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>

并使用ref名称作为参数:

@ViewChild('galleryContainer') galleryContainer: ElementRef;

EDIT

忘记提及所声明的任何视图子项仅在视图初始化后才可用 . 第一次发生这种情况是在 ngAfterViewInit 中(导入并实现 AfterViewInit 接口) .

The ref name must not contain dashes or this will not work

3 years ago

有时,如果在访问组件时尚未初始化组件,则会收到错误消息,指出子组件未定义 .

但是,即使您访问AfterViewInit中的子组件,有时@ViewChild仍然返回null . 问题可能是由* ngIf或其他指令引起的 .

解决方案是使用@ViewChildren而不是@ViewChild,并订阅组件准备好时执行的更改订阅 .

例如,如果在父组件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 the child component
    });
  }
}

3 years ago

订阅更改

@ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>

确认工作,结合 setTimeout()notifyOnChanges() 并仔细检查 null .

任何其他方法都会产生不可靠的结果,很难测试 .