我有一个动态组件加载程序,并且我需要通过服务传递数据。例如,如果我在click
上触发函数,但在OnInit
上触发函数,则可以显示数据。
更新: 工作StackBlitz
app.component.html
<app-answer-set></app-answer-set>
header.component.html
<ng-template appHeaderHost></ng-template>
header.component.ts
export class HeaderComponent implements OnInit {
@Input() component;
@ViewChild(HeaderHostDirective) headerHost: HeaderHostDirective;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
ngOnInit() {
this.loadComponent();
}
loadComponent() {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
const viewContainerRef = this.headerHost.viewContainerRef;
viewContainerRef.createComponent(componentFactory);
}
}
header-host.directive.ts
export class HeaderHostDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
header-data.service.ts
export class HeaderDataService {
private headerDataSource = new Subject<any>();
headerData$ = this.headerDataSource.asObservable();
constructor() { }
setHeaderData(data: any) {
this.headerDataSource.next(data);
}
}
answer-set.component.html
<app-header [component]="component"></app-header>
<button (click)="setHeaderData()">click</button>
answer-set.component.ts
export class AnswerSetComponent implements OnInit {
component: any = AnswerSetHeaderDetailsComponent;
constructor(private headerDataService: HeaderDataService) { }
ngOnInit() {
this.setHeaderData();
}
setHeaderData() {
const data = [{name: 'Header stuff'}];
this.headerDataService.setHeaderData(data);
}
}
answer-set-header-details.html
<dt>First:</dt>
<dd>Description</dd>
<dt>Second</dt>
<dd>Description</dd>
<p>
data will show on click of button but not <code>onInit</code>:
</p>
<p>
{{headerData}}
</p>
answer-set-header-details.component.ts
export class AnswerSetHeaderDetailsComponent implements OnInit {
constructor(private headerDataService: HeaderDataService) { }
headerData: any;
ngOnInit() {
this.headerDataService.headerData$
.subscribe(data => {
this.headerData = data[0].name;
});
}
}
答案 0 :(得分:0)
运行Angular documentation之后,我发现需要将数据传递给componentRef实例,如下所示:
Future<FooState> bar(int event)
经过一些重构,我最终将组件和数据都通过服务传递,请参见更新后的StackBlitz以获取工作示例。
最终,我希望传递多个组件,但现在可以使用。
header.component.html
int
header.component.ts
Event
header.service.ts
(<IHeader>componentRef.instance).data = headerItems.data;
header.ts
<ng-template appHeaderHost></ng-template>
main.component.html
/* ... */
export class HeaderComponent implements OnInit {
@ViewChild(HeaderHostDirective) headerHost: HeaderHostDirective;
subscriptionManager = new Subscription();
constructor(
private headerService: HeaderService,
private componentFactoryResolver: ComponentFactoryResolver
) {
const headerConfigSubscription = this.headerService.headerConfig$
.subscribe((headerItems: HeaderItem) => {
this.loadComponent(headerItems);
});
this.subscriptionManager
.add(headerConfigSubscription);
}
ngOnInit() {
}
loadComponent(headerItems: HeaderItem) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(headerItems.component);
const viewContainerRef = this.headerHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
(<IHeader>componentRef.instance).data = headerItems.data ? headerItems.data : null;
}
ngOnDestroy() {
/**
* @description Unsubscribe from all subscriptions
* to prevent memory leaks
*/
this.subscriptionManager.unsubscribe();
}
}
main.component.ts
/* ... */
export class HeaderService {
private headerConfigSource = new Subject<any>();
headerConfig$ = this.headerConfigSource.asObservable();
constructor() { }
configureHeaderItems(headerItems: HeaderItem) {
this.headerConfigSource.next(headerItems);
}
}
main.module.ts
/* ... */
export interface IHeader {
data: any;
}
export interface IHeaderItem {
component: Type<any>;
data?: any;
}
export class HeaderItem implements IHeaderItem {
constructor(
public component: Type<any>,
public data?: any
) {
this.component = component;
this.data = data;
}
}
main-header-details.component.html
<app-header></app-header>
main-header-details.component.ts
export class MainComponent implements OnInit {
headerItems: HeaderItem;
constructor(private headerService: HeaderService) { }
ngOnInit() {
this.configureHeaderItems();
}
configureHeaderItems() {
this.headerItems = new HeaderItem(MainHeaderDetailsComponent, {});
this.getHeaderItemData();
}
/**
* @description This is where we would make the API call and get the data
* but we can mock it for now
*/
getHeaderItemData() {
const data = {
name: 'I am loaded dynamically!'
};
this.headerItems.data = data;
this.headerService.configureHeaderItems(this.headerItems);
}
}