Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested Dynamic Components Break With ComponentFactoryResolver #10762

Closed
rbj325 opened this issue Aug 12, 2016 · 12 comments
Closed

Nested Dynamic Components Break With ComponentFactoryResolver #10762

rbj325 opened this issue Aug 12, 2016 · 12 comments

Comments

@rbj325
Copy link

rbj325 commented Aug 12, 2016

I'm submitting a ... (check one with "x")

[ x ] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior
When trying to render nested dynamic components via the ComponentFactoryResolver I receive an exception/error message:

browser_adapter.js:84Error: Expression has changed after it was checked. Previous value: 'CD_INIT_VALUE'. Current value: 'null'. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?

Expected/desired behavior

It should render the nested dynamic controls. This had worked until the introduction of the ComponentFactoryResolver. See: https://plnkr.co/edit/JRyqou9yC6LvSRrCR3eA?p=preview

Reproduction of the problem

Here is the plunkr recreating the issue: http://plnkr.co/edit/NzT4a7GEAB7k4yqeZrs0?p=preview

What is the expected behavior?

I should be able to render a control via ComponentFactoryResolver which in turn also renders multiple controls via ComponentFactoryResolver.

In my use case, I am rendering a form wizard made up of several dynamic components. In one of those dynamic components I am pulling fields defined in the database to render a set of user controlled fields.

What is the motivation / use case for changing the behavior?

It used to work.

Please tell us about your environment:

  • Angular version: 2.0.0-rc.5
  • Browser: [all ]
  • Language: [all ]
@rbj325
Copy link
Author

rbj325 commented Aug 13, 2016

Plunker repro added.

@thecritic
Copy link

@rbj325 Have you been able to solve this ?

@rbj325
Copy link
Author

rbj325 commented Aug 15, 2016

@thecritic No, the only thing I've seen is to try to manually call ChangeDetectorRef.detectChanges manually but no matter where you do that the error persists.

@jpleclerc
Copy link

I have the same problem. I dynamically create a modal window and attach it to the app component. Then I dynamically create a component in the modal window. It crashes when loading the content of the modal.

@jpleclerc
Copy link

jpleclerc commented Aug 15, 2016

For anyone looking for a dirty hack, wrap your code in a setTimeout():

public ngAfterViewInit(): any {
    setTimeout(() => {
        let modalFactory = this.componentResolver.resolveComponentFactory(<any>this.modalInstance.config.content);
        this.componentInstance = this.container.createComponent(modalFactory, null, this.injector);
    }, 1);
}

@rbj325
Copy link
Author

rbj325 commented Aug 15, 2016

@jpleclerc That work around does not work for me because the dynamic form requires the control to be present when it's rendering. It did remove the change detection error though.

@gluix
Copy link

gluix commented Aug 19, 2016

Use the "AfterContentInit" lifecycle-hook to init/update your nested dynamic-component.

public ngAfterContentInit() {
  let modalFactory = this.componentResolver.resolveComponentFactory(<any>this.modalInstance.config.content);
  this.componentInstance = this.container.createComponent(modalFactory, null, this.injector);
}

updated your plunker:
http://plnkr.co/edit/EasYKceQTBC9yA4Xsma8?p=preview

@rbj325
Copy link
Author

rbj325 commented Aug 19, 2016

@gluix Awesome, I think that's the only life cycle hook I didn't try.

@RoyiNamir
Copy link

@gluix - I know that ngAfterContentInit is called before ngAfterViewInit but why does it work when I put it in that location ? does it automatically do another cycle check ( later ,inside ngAfterViewInit)?

@regosnet
Copy link

regosnet commented Feb 7, 2018

public ngAfterViewInit(): any {
setTimeout(() => {
let modalFactory = this.componentResolver.resolveComponentFactory(this.modalInstance.config.content);
this.componentInstance = this.container.createComponent(modalFactory, null, this.injector);
}, 1);
}

That worked!

@imben1109
Copy link

I got a similar problem. It is finally solved by change ngAfterViewInit to ngOnInit or add componentRef.changeDetectorRef.detectChanges()

https://stackoverflow.com/questions/50539133/angular-create-dynamic-component-recursively/50539250?noredirect=1#comment88090372_50539250

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants