Change detection not working when creating a component via ComponentFactoryResolver
Asked Answered
I

2

7

I have a component, creating another component with ComponentFactoryResolver. It seems to work fine, I can access data through the @Input. Problem is ngOnChanges never gets called when the component boots up, or when the data changes. However, it does trigger if I create the component the normal way, with it's selector in HTML. That isn't dynamic though, so I am left with ComponentFactoryResolver. Is this normal behavior?

My parent component has it's input:

@ViewChild( MyDirective ) myHost: MyDirective;

Then it creates child components whose inputs are like this:

@Input('key') key: String;
@Input('index') index: number;

and I'm creating the component like this:

let item = new Item(ItemDropdownComponent, this.key, 0);
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(item.component);
let viewContainerRef = this.myHost.viewContainerRef;
viewContainerRef.clear();
let componentRef = viewContainerRef.createComponent(componentFactory);
(<ItemInterfaceComponent>componentRef.instance).key = item.key;
(<ItemInterfaceComponent>componentRef.instance).index = item.index;
Intercourse answered 30/3, 2017 at 8:42 Comment(0)
P
12

That's expected behavior. You can invoke change detection explicitely though

componentRef.changeDetectorRef.detectChanges();
Pilewort answered 30/3, 2017 at 8:44 Comment(5)
Hmmm, I think I'm using this wrong but you may be on the right track. I'll learn more about how to use detectChanges and keep you posted. Thanks!Intercourse
Having a hard time implementing this. I thought maybe this would turn on change detection, but it seems when I add this line immediately after I createComponent it doesn't pass in the variables immediately after, and after that no change detection. So I tried calling detectChanges() after every time I change the variables, thinking maybe it's a signal, but it doesn't trigger ngOnChange either. I've been looking for tutorials on it, the angular docs aren't really clear to me in this case.Intercourse
It will run change detection for view bindings, but not for inputs. ngOnChange is only called when input bindings are updated, but there are no input bindings for dynamically added components. You can just move the code in ngOnChanges() to another method and call it from ngOnChanges() so it is executed when you use your component "in a normal way" or call this method like componentRef.instance.foo() if you add the component dynamically. You can also call componentRef.instance.ngOnChanges().Conto
Yeah sorry, I didn't also think of this at first yesterday.Conto
@GünterZöchbauer Having the same problem, and your strategy doesn't help. I'll post a question!Osseous
H
0

If you run change detection manually be aware that it will run for the component and all it children, means the full branch. So you need to think of detaching other children when creating new one.

This issue is tracked in: https://github.com/angular/angular/issues/22010

Hydrophobic answered 30/3, 2018 at 12:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.