I have dynamically added a component on the click of a button .
Below is the code for my widget . Simple div with color property being set as input.
I have faced with the same issue: component processes input data and creates own appearance based on this data. The only one issue was adding component as regular one with html template (and predefined input data) and dynamically with componentFactory
and setting data after ngInit
angular event. It broke all initialization component logic due to triggering ngInit
event before setting input data for component. One possible solution might be adding flexible component initialization based on allow initialization flag, that is set before adding this component and after settings input data.
initComponentData() {
const canInitData = !this.appService.deniedInitData.value;
if (canInitData) {
this.initData();
} else {
this.subscriptions.push(
this.appService.deniedInitData.pipe(filter(x => !x),take(1)).subscribe(() => {
this.initData();
}));
}
}
appService - Injectable angular service with
deniedInitData: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
Place when we are dynamically adding component:
this.appService.deniedInitData.next(true);
const cmpRef = this.viewContainerRef.createComponent(this.componentFactory, 0);
const instance = cmpRef.instance;
instance.someProp = 'someValue';
this.appService.deniedInitData.next(false);
var cmpRef = this.viewContainerRef.createComponent(this.componentFactory, 0);
cmpRef.instance.someProp = 'someValue';
cmpRef.instance.someObservable.subscribe(val => this.someProp = val);
I will put this article if you can't find it in google https://netbasal.com/dynamically-creating-components-with-angular-a7346f4a982d It explains perfectly how to pass data, It helps me a lot to understand the resolveComponentFactory
, Sorry for the answer is more like a comment but I do not have enough reputation.