LoginSignup
28
19

More than 5 years have passed since last update.

Angular2で動的コンポーネントを生成する

Last updated at Posted at 2016-12-07

Angular2にて動的にコンポーネントを生成するサンプルコードです。

sample-capture-edit.png

動作確認環境

ソースコード

app/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import {
  Component,
  ComponentFactoryResolver,
  EventEmitter,
  NgModule,
  OnInit,
  OnDestroy,
  ViewContainerRef
} from '@angular/core';
import { Observable } from 'rxjs/Rx'; // MEMO: plunkerの場合は'rxjs/Rx'、ローカルでangular-cliの場合は'rxjs'


/**
 * 動的に生成するサンプルコンポーネント
 */
@Component({
  selector: 'app-sample',
  template: `
    <div style="margin: 1rem; padding: 1rem; border: 1px solid #eee;">
      <button (click)="closeButton_Clicked()">CLOSE</button> No. {{_no}}
    </div>
  `,
})
export class SampleComponent implements OnInit, OnDestroy
{
  /** クローズイベント */
  private _closing = new EventEmitter<{}>();

  /** コンポーネント生成元から受け取るパラメータ */
  private _no: number = 0;

  /** クローズイベントのgetプロパティ */
  public get closing(): Observable<{}>
  {
    return this._closing;
  }

  /** コンポーネント生成元から受け取るパラメータのsetプロパティ */
  public set no(value: number)
  {
    this._no = value;
  }

  /**
   * Angular Lifecycle Hooks: OnInit
   */
  public ngOnInit(): void
  {
    console.log(`SampleComponent.ngOnInit >> no="${this._no}"`);
  }

  /**
   * Angular Lifecycle Hooks: OnDestroy
   */
  public ngOnDestroy(): void
  {
    console.log(`SampleComponent.ngOnDestroy >> no="${this._no}"`);
  }

  /**
   * CLOSEボタンのクリックイベントハンドラ
   */
  private closeButton_Clicked(): void
  {
    // クローズイベントを発行
    this._closing.emit({});
  }
}


/**
 * メインAppコンポーネント
 */
@Component({
  selector: 'my-app',
  template: `
    <div style="padding: 1rem; border: 1px solid #eee;">
      <h2>Angular2 Dynamic Component Sample</h2>
      <button (click)="createButton_Clicked()">CREATE</button>
    </div>
  `,
})
export class App
{
  public constructor(
    private _componentFactoryResolver: ComponentFactoryResolver,
    private _viewContainerRef: ViewContainerRef)
  {
  }

  /**
   * CREATEボタンのクリックイベントハンドラ
   */
  private createButton_Clicked(): void
  {
    // コンポーネント生成器を初期化
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(SampleComponent);

    // 動的にコンポーネントを生成
    const componentRef = this._viewContainerRef.createComponent(componentFactory);

    // 動的に生成したコンポーネントにパラメータを渡す
    componentRef.instance.no = Math.floor(Math.random() * 100); // 0~99のランダム値を渡す

    // closingイベントを受けたらコンポーネント破棄する
    componentRef.instance.closing.subscribe(() => {
      componentRef.destroy();
    });
  }
}


/**
 * アプリケーションモジュール
 */
@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, SampleComponent ], // 独自のcomponent/directiveをdeclarationsに指定する
  bootstrap: [ App ],
  entryComponents: [ SampleComponent ], // 動的に生成するcomponentをentryComponentsに指定する
})
export class AppModule
{
}

platformBrowserDynamic().bootstrapModule(AppModule);
28
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
19