使用Directive Angular时@ViewChild为null

时间:2018-07-27 09:37:52

标签: angular angular-directive viewchild

我正在关注this教程,该教程如何在运行时动态加载组件,并且遇到@ViewChildundefined的问题。

这是我的指令。

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
    selector: '[dynamic-event]'
})

export class EventDirective {
    constructor(public viewContainerRef: ViewContainerRef) {}
}

要在其中注入模板的组件(feed.component.html):

<ng-template dynamic-event></ng-template>

feed.component.ts

import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { Event } from '../../models/event';
import { FeedService } from '../../services/feed.service';
import { EventDirective } from '../../directives/event.directive';
import { EventComponent } from '../event.component/event.component';

@Component({
  selector: 'app-feed',
  templateUrl: './feed.component.html',
  styleUrls: ['./feed.component.css']
})
export class FeedComponent implements OnInit {

  //feeds
  feeds: Event[];

  //Get directive which contains ViewContainerRef
  @ViewChild(EventDirective) eventHost: EventDirective;

  constructor(private feedService: FeedService, 
    private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {
    //this.getFeeds();
  }
  ngAfterViewChecked() {
    this.getFeeds();
  }

  getFeeds(): void {
    this.feedService
    .getFeeds()
    .subscribe(o => 
      { 
        this.feeds = o;
        this.populateFeeds();
      });
  }
  populateFeeds(): void {
    //resolve my component dynamically 
    let componentFactory = this.componentFactoryResolver.resolveComponentFactory(EventComponent);
    //get FeedComponent's ViewContainer (serves as parent viewContainer)
    let viewContainerRef = this.eventHost.viewContainerRef;
    viewContainerRef.clear();

    if (this.feeds !== undefined || this.feeds !== null || this.feeds.entries.length !== 0){
      this.feeds.forEach(x => {
        let component = viewContainerRef.createComponent(componentFactory);
        (<EventComponent>component.instance).event = x;
      });      
    }
  }
}

我的@ViewChild未定义,我不确定为什么。有帮助吗?

2 个答案:

答案 0 :(得分:1)

我认为,如果没有实际的本机HTML元素,您将无法做到这一点。

要进行验证,请尝试使用<div dynamic-event></div>

ng-template是虚拟元素,在使用(某处)之前,不会放置在生成的HTML标记内-由于没有带指令的元素,因此字段未定义。

答案 1 :(得分:1)

我发现了问题。

由于我没有使用Angular的cli命令ng generate directive,该命令将在app.module声明数组中声明了我的指令,所以我收到了此错误。

我手动添加了EventDirective,现在可以使用了:

这里是一个例子:

@NgModule({
  declarations: [
    AppComponent,
    FeedComponent,
    EventComponent,
    EventDirective 
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [], 
  entryComponents: [EventComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }