Angular 2 @ViewChild возвращает undefined

Я просмотрел несколько связанных сообщений и документации, но все еще не могу получить ожидаемое поведение от @ViewChild.

в конечном счете, я пытаюсь установить положение прокрутки в div. Этот элемент не является компонентом, а обычным div В моем HTML.

чтобы выполнить это, я пытаюсь использовать @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>

мой вывод прост: мой элемент: undefined.

Как вы можете видеть, в настоящее время я пытаюсь получить доступ к элементу по ID, но пробовал имя класса. Может ли кто-нибудь предоставить более подробную информацию о том, что ожидает запрос селектора ViewChild?

Я также видел примеры, когда хэш " # " используется в качестве селектора idendifier, который использует @ViewChild -- -- но это вызывает ошибку разбора шаблона для меня с #gallery-container.

Я не могу придумать ничего другого, что могло бы быть неправильно здесь. Вся помощь приветствуется, спасибо!

полный код доступен здесь: https://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page

3 ответов


попробуйте вместо этого использовать ссылку в шаблоне:

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

редактировать

забыл упомянуть, что любой объявленный таким образом дочерний вид доступен только после инициализации представления. В первый раз это происходит в ngAfterViewInit (импорт и реализация AfterViewInit интерфейс).

имя ref не должно содержать тире или это не будет работать


иногда, если компонент еще не инициализирован при доступе к нему, вы получаете ошибку, которая говорит, что дочерний компонент не определен.

однако, даже если вы получаете доступ к дочернему компоненту в 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
    });
  }
}

подписка на изменения на

@ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>

подтверждена работа в сочетании с setTimeout() и notifyOnChanges() и осторожны null проверка.

любой другой подход дает ненадежные результаты, и это трудно проверить.