Я следую руководству это о том, как динамически загружать компоненты во время выполнения, и столкнулся с проблемами, когда мой @ViewChild был undefined.
Вот моя директива.
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 не определен, и я не знаю почему. Любая помощь?





Я думаю, вы не сможете этого сделать без собственно собственного HTML-элемента.
Для проверки попробуйте с <div dynamic-event></div>
ng-template является виртуальным элементом и не помещается в сгенерированную разметку HTML, пока не используется (где-то) - так как нет элемента с директивой, поле не определено.
чтобы быть более точным, сам ng-шаблон будет закомментирован в html, если он не упомянут в ngIf
@monstertjie_za point устанавливает директиву для элемента html, такого как div
@SurajRao этого не знал. Вы уверены, что это произойдет в производственной сборке? Может, это просто в режиме разработки?
@Antoniossss Я пробовал <div dynamic-event> </div>, не решил проблему
Все еще не определено ?? Не могли бы вы создать stackblitz, чтобы воспроизвести это?
думаю будет пустой комментарий
Здесь вы можете видеть, что я ввел свою настраиваемую директиву. stackblitz.com/edit/…
@Antoniossss Ваш ответ выше неверен. У меня он работает только с <ng-template dynamic-event> </ng-template> в качестве моего шаблона html
Я нашел свою проблему.
Поскольку я не использовал команду 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 { }
Мой feed.component.html теперь выглядит так: <p> Здесь загружаются динамические события </p> <div> <ng-template dynamic-event> </ng-template> </div> К сожалению, @ViewChild все еще не определен