141

ディレクティブを含む HTML を手動でコンパイルしたいと考えています。$compileAngular 2に相当するものは何ですか?

たとえば、Angular 1 では、HTML のフラグメントを動的にコンパイルして DOM に追加できました。

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

9 に答える 9

136

Angular 2.3.0 (2016-12-07)

すべての詳細を確認するには:

実際の動作を確認するには:

プリンシパル:

1) テンプレートを作成
2) コンポーネントを作成
3) モジュールを作成
4) モジュールをコンパイル
5) ComponentFactory を作成 (およびキャッシュ)
6) ターゲットを使用してそのインスタンスを作成

コンポーネントの作成方法の簡単な概要

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

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

を作成(およびキャッシュ)する方法のコード スニペットComponentFactory

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

上記の結果を使用するコード スニペット

  // 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;
        //...
    });

ここで読むすべての詳細を含む完全な説明、または実際のを観察してください

.

.

OBSOLETE - Angular 2.0 RC5 関連 (RC5 のみ)

以前の RC バージョンの以前の解決策を確認するには、この投稿の履歴を検索してください。

于 2016-05-05T07:31:32.723 に答える
35

注: @BennyBottema がコメントで言及しているように、DynamicComponentLoader は廃止されたため、この回答も廃止されました。


Angular2 には$compileに相当するものはありません 。ES6 クラスを使用DynamicComoponentLoaderおよびハックして、コードを動的にコンパイルできます (このplunkを参照)。

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

function compileToComponent(template, directives) {
  @Component({ 
    selector: 'fake', 
    template , directives
  })
  class FakeComponent {};
  return FakeComponent;
}

@Component({
  selector: 'hello',
  template: '<h1>Hello, Angular!</h1>'
})
class Hello {}

@Component({
  selector: 'my-app',
  template: '<div #container></div>',
})
export class App implements OnInit {
  constructor(
    private loader: DynamicComponentLoader, 
    private elementRef: ElementRef,
  ) {}

  ngOnInit() {} {
    const someDynamicHtml = `<hello></hello><h2>${Date.now()}</h2>`;

    this.loader.loadIntoLocation(
      compileToComponent(someDynamicHtml, [Hello])
      this.elementRef,
      'container'
    );
  }
}

ただし、htmlパーサーがangular2コア内にあるまでのみ機能します。

于 2016-01-14T09:36:59.663 に答える
3

コンポーネントのインスタンスを動的に作成して DOM にアタッチするには、次のスクリプトを使用でき、Angular RCで動作する必要があります。

html テンプレート:

<div>
  <div id="container"></div>
  <button (click)="viewMeteo()">Meteo</button>
  <button (click)="viewStats()">Stats</button>
</div>

ローダー コンポーネント

import { Component, DynamicComponentLoader, ElementRef, Injector } from '@angular/core';
import { WidgetMeteoComponent } from './widget-meteo';
import { WidgetStatComponent } from './widget-stat';

@Component({
  moduleId: module.id,
  selector: 'widget-loader',
  templateUrl: 'widget-loader.html',
})
export class WidgetLoaderComponent  {

  constructor( elementRef: ElementRef,
               public dcl:DynamicComponentLoader,
               public injector: Injector) { }

  viewMeteo() {
    this.dcl.loadAsRoot(WidgetMeteoComponent, '#container', this.injector);
  }

  viewStats() {
    this.dcl.loadAsRoot(WidgetStatComponent, '#container', this.injector);
  }

}
于 2016-07-25T23:34:54.767 に答える