1

Using Angular 2.0 (final), how can I load a Component inside of a DOM element created by a non-Angular library, after app bootstrapping and Component rendering has occurred?

I had previously used DynamicComponentLoader.loadNextToLocation() to load Components inside of DOM elements, but that was deprecated as of RC5.

The Problem (TL;DR)

I'm attempting to use Angular 2.0 to insert a dynamically-created Component inside of a popup window that is generated at runtime by an external, non-Angular library (specifically, an InfoWindow/Popup for an ESRI ArcGIS JavaScript API 3.x Map).

Since the popup window is generated entirely by the external library after app bootstrap and the parent Component's ngAfterViewInit()/ngAfterContentInit() events occur, any #ref tag present in the newly-added popup's DOM is ignored. And without a #ref tag and the derived ViewContainerRef, I can't figure out how to insert new Components inside of the popup.

The Code

I'm using the same setup shown in this SO answer, namely:

@ViewChild('dynamicContentPlaceHolder', {read: ViewContainerRef})
protected dynamicComponentTarget: ViewContainerRef;

// this will be reference to dynamic content - to be able to destroy it
protected componentRef: ComponentRef<IHaveDynamicData>;

this.compiler
.compileComponentAsync<IHaveDynamicData>(dynamicType, MyModule)
.then((factory: ng.ComponentFactory<IHaveDynamicData>) =>
{
    // our component will be inserted after #dynamicContentPlaceHolder
    this.componentRef = this.dynamicComponentTarget.createComponent(factory,     0);

    // and here we have access to our dynamic component
    let component: IHaveDynamicData = this.componentRef.instance;

    component.entity = this.entity;
});

Note: Based on @MarkRajcok's post here, I had the idea to try ChangeDetectorRef.detectChanges() to trigger a re-render of the parent Component, with the hope that a #ref tag in the newly-created popup's DOM would be picked up and compiled. But, likely due to my inexperience with Angular 2.0, I've so far had no luck. Perhaps this a misguided approach all together?

Community
  • 1
  • 1
Aaron Jessen
  • 404
  • 5
  • 14

1 Answers1

1

i did this, but it feels like a total hack... it did render the component at the dom element location, though

var me = this;
setTimeout(function(){ 
  var simpleComponent = me.componentFactoryResolver.resolveComponentFactory(SimpleComponent);
  me.componentRef = me.dynamicTarget.createComponent(simpleComponent);
                var node = document.getElementById("theTest");
                node.appendChild(me.componentRef['_hostElement'].nativeElement);
}, 10);
Marc Gusmano
  • 46
  • 1
  • 4
  • Thanks for your answer, Marc. While this isn't an Angular-friendly way of doing things, I simply can't figure out how else to accomplish my goal. Cheers! – Aaron Jessen Sep 26 '16 at 16:48
  • just add maybe a parent
    . I would just hide the #dynamicTarget since the new created components will populate next to #dynamicTarget. I guess having 1 useless hidden element is better than manipulating your DOM with javascript append.
    – ralcazar Oct 06 '16 at 00:52