web-dev-qa-db-ja.com

@ViewChildは未定義を返します

何らかの理由で、私のAngular 5アプリの@ViewChildは機能しません。コンポーネントで次のように定義しました。

case-detail.component.html:

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

私は(コンストラクタの上にある)コントローラに@ViewChildを次のように実装しました:

case-detail.component.ts

@ViewChild('innerTabContent') tabContentElement: ElementRef;

そして、私はコンポーネントでここにアクセスしたいと思います:case-detail.component.ts

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

AfterViewInitインターフェースを実装しました。 ngAfterViewInit()が正しく呼び出されます。ただし、this.tabContentElementは常にundefinedです。

どんな助けでも大歓迎です:)

11
dave0688

ViewChild()は、最新のプランカーAngularバージョンで正常に機能し、説明したシナリオに対応しています。

このプランカーでのデモ: https://plnkr.co/edit/KzWnkE5Hvp7NUow6YAxy

コンポーネント:

ngAfterViewInit() {
    console.log(this.testView); // correctly outputs the element in console, not undefined
}
  • ElementRefとViewChildが '@ angular/core'から正しくインポートされていることを確認します。

  • AfterViewInitの時点で要素が存在しない可能性があります(*ngIf、例えば。(あなたのコメントによるとケースがそうです)

後者の場合は、ラッパー要素とViewChildrenを使用できます。これにより、新しい子要素が追加されたときにイベントが発生します-ドキュメントの詳細はこちら: https://angular.io/api/core/ViewChildren

この質問に従ってネイティブdivに問題がある可能性があることに注意してください: @ ViewChildrenは動的に追加されたDOM要素で更新されません ですが、これは新しいコンポーネントを使用することで回避できますたとえば、divをラップします。

編集

または、タイムアウトを使用して、コンポーネントがレンダリングされるのを待つこともできます。私はこの解決策を「汚い」と思っていると言わなければなりませんが、それがあなたのために働くのはうれしいです:)

7
Pac0

ただし、AfterViewInitの子コンポーネントにアクセスした場合でも、@ViewChildはまだnullを返していました。問題は*ngIfまたはその他のディレクティブ。

解決策は@ViewChildren の代わりに @ViewChildおよびコンポーネントの準備ができたときに実行されるchangesサブスクリプションをサブスクライブします。

たとえば、親コンポーネント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
    });
  }
}
5
Marco Barbero

この質問に対する別の答えは、アクセスしたときに、子コンポーネントがまだレンダリングされない場合があります。私にとっては、子コンポーネントがまだ存在しない* ngIfが原因でした。例として、

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

そして、親の.tsファイルで、checkがfalseに設定されているときにchildItemにアクセスしようとします。

0
dilantha111