Search code examples
angulartypescriptangular2-compilerversion-compatibility

Equivalent of $compile in Angular 2


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);

Solution

  • 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