garethdn
garethdn

Reputation: 12351

Bindings not working in dynamically loaded component

I'm encountering a problem where if I dynamically load a component, none of the bindings in the template are working for me. As well as this the ngOnInit method is never triggered.

loadView() {
    this._dcl.loadAsRoot(Injected, null, this._injector).then(component => {
      console.info('Component loaded');
    })
  }

Dynamically loaded component

import {Component, ElementRef, OnInit} from 'angular2/core'

declare var $:any

@Component({
    selector: 'tester',
    template: `
      <h1>Dynamically loaded component</h1>
        <span>{{title}}</span>
    `
})

export class Injected implements OnInit {

    public title:string = "Some text"

    constructor(){} 

    ngOnInit() {
      console.info('Injected onInit');
    }

}

This is my first time using dynamically loaded components so I think may be attempting to implement it incorrectly.

Here's a plunkr demonstrating the issue. Any help would be appreciated.

Upvotes: 5

Views: 1761

Answers (2)

PARUL DIXIT
PARUL DIXIT

Reputation: 1

No need to clean component instance from DOM. use 'componentRef' from angular2/core package to create and dispose component instance. use show() to load the modal component at desired location and hide() to dispose the component instance before calling loadIntoLocation secondtime.

for eg:

@Component({
  selector: 'app',
  template: `
    <router-outlet></router-outlet>
    <div #modalContainer></div>
 `,
  directives: [RouterOutlet]
})
export class AppComponent {
  private component:Promise<ComponentRef>;

  constructor(public el:ElementRef) {}

  getElementRef():ElementRef {
    return this.el;
  }

  show(){
    this.component = this._dcl.loadIntoLocation(ModalComponent,this.appComponent.getElementRef(), 'modalContainer').then(component => {console.log('Component loaded')})
  }

  hide(){
    this.component.then((componentRef:ComponentRef) => {
      componentRef.dispose();
      return componentRef;
    });
  }
}

Upvotes: 0

garethdn
garethdn

Reputation: 12351

As Eric Martinez pointed out this is a known bug related to the use of loadAsRoot. The suggested workaround is to use loadNextToLocation or loadIntoLocation.

For me this was problematic as the component I was trying to dynamically load was a modal dialog from inside a component with fixed css positioning. I also wanted the ability to load the modal from any component and have it injected into the same position in the DOM regardless of what component it was dynamically loaded from.

My solution was to use forwardRef to inject my root AppComponent into the component which wants to dynamically load my modal.

constructor (
    .........
    .........
    private _dcl: DynamicComponentLoader,
    private _injector: Injector,
    @Inject(forwardRef(() => AppComponent)) appComponent) {

    this.appComponent = appComponent;
}

In my AppComponent I have a method which returns the app's ElementRef

@Component({
    selector: 'app',
    template: `
        <router-outlet></router-outlet>
        <div #modalContainer></div>
    `,
    directives: [RouterOutlet]
})

export class AppComponent {

    constructor(public el:ElementRef) {}

    getElementRef():ElementRef {
        return this.el;
    }

}

Back in my other component (the one that I want to dynamically load the modal from) I can now call:

this._dcl.loadIntoLocation(ModalComponent, this.appComponent.getElementRef(), 'modalContainer').then(component => {
    console.log('Component loaded')
})

Perhaps this will help others with similar problems.

Upvotes: 6

Related Questions