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;
Jus10
  • 14,519
  • 21
  • 52
  • 77

2 Answers2

12

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

componentRef.changeDetectorRef.detectChanges();
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    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! – Jus10 Mar 30 '17 at 09:08
  • 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. – Jus10 Mar 30 '17 at 21:36
  • 5
    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()`. – Günter Zöchbauer Mar 31 '17 at 05:14
  • Yeah sorry, I didn't also think of this at first yesterday. – Günter Zöchbauer Mar 31 '17 at 09:33
  • 1
    @GünterZöchbauer Having the same problem, and your strategy doesn't help. I'll post a question! – LppEdd Feb 01 '19 at 15:21
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

Royalsmed
  • 212
  • 1
  • 4
  • 16