Equivalent of $compile in Angular 2

pixelbits picture pixelbits · Jan 14, 2016 · Viewed 68.1k times · Source

I want to manually compile some HTML containing directives. What is the equivalent of $compile in Angular 2?

For example, in Angular 1, I could dynamically compile a fragment of HTML and append it to the DOM:

var e = angular.element('<div directive></div>');
element.append(e);
$compile(e)($scope);

Answer

Radim K&#246;hler picture Radim Köhler · May 5, 2016

Angular 2.3.0 (2016-12-07)

To get all the details check:

To see that in action:

The principals:

1) Create Template
2) Create Component
3) Create Module
4) Compile Module
5) Create (and cache) ComponentFactory
6) use Target to create an Instance of it

A quick overview how to create a Component

createNewComponent (tmpl:string) {
  @Component({
      selector: 'dynamic-component',
      template: tmpl,
  })
  class CustomDynamicComponent  implements IHaveDynamicData {
      @Input()  public entity: any;
  };
  // a component for this particular template
  return CustomDynamicComponent;
}

A way how to inject component into NgModule

createComponentModule (componentType: any) {
  @NgModule({
    imports: [
      PartsModule, // there are 'text-editor', 'string-editor'...
    ],
    declarations: [
      componentType
    ],
  })
  class RuntimeComponentModule
  {
  }
  // a module for just this Type
  return RuntimeComponentModule;
}

A code snippet how to create a ComponentFactory (and cache it)

public createComponentFactory(template: string)
    : Promise<ComponentFactory<IHaveDynamicData>> {    
    let factory = this._cacheOfFactories[template];

    if (factory) {
        console.log("Module and Type are returned from cache")

        return new Promise((resolve) => {
            resolve(factory);
        });
    }

    // unknown template ... let's create a Type for it
    let type   = this.createNewComponent(template);
    let module = this.createComponentModule(type);

    return new Promise((resolve) => {
        this.compiler
            .compileModuleAndAllComponentsAsync(module)
            .then((moduleWithFactories) =>
            {
                factory = _.find(moduleWithFactories.componentFactories
                                , { componentType: type });

                this._cacheOfFactories[template] = factory;

                resolve(factory);
            });
    });
}

A code snippet how to use the above result

  // here we get Factory (just compiled or from cache)
  this.typeBuilder
      .createComponentFactory(template)
      .then((factory: ComponentFactory<IHaveDynamicData>) =>
    {
        // Target will instantiate and inject component (we'll keep reference to it)
        this.componentRef = this
            .dynamicComponentTarget
            .createComponent(factory);

        // let's inject @Inputs to component instance
        let component = this.componentRef.instance;

        component.entity = this.entity;
        //...
    });

The full description with all the details read here, or observe working example

.

.

OBSOLETE - Angular 2.0 RC5 related (RC5 only)

to see previous solutions for previous RC versions, please, search through the history of this post