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;

2 Answers 2

12

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

componentRef.changeDetectorRef.detectChanges();
Sign up to request clarification or add additional context in comments.

5 Comments

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!
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.
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().
Yeah sorry, I didn't also think of this at first yesterday.
@GünterZöchbauer Having the same problem, and your strategy doesn't help. I'll post a question!
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.