Search code examples
angularangular-directiveviewchild

@ViewChild is null when using Directive Angular


I am following this tutorial on how to load components dynamically at runtime, and running into problems with my @ViewChild being undefined.

Here is my Directive`.

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

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

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

Component where to inject template (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;
      });      
    }
  }
}

My @ViewChild is undefined, and I am not sure why. Any help?


Solution

  • I found my problem.

    Because I was not using Angular's cli command ng generate directive, which would have declared my Directive in the app.module declarations array, I was receiving this error.

    I manually added my EventDirective, and now it works:

    Here is an example:

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