少し前に Angular2 がリリースされました。設計が色々モダンになっているので Angular1 より Angular2 を使いたいのですが、 Angular1 で書かれたコードがある場合、いきなり全部を移行するのも難しいです。

そこで Angular2 のコンポーネントを Angular1 から使う方法を調べてみました。

準備

Angular2 と、その依存モジュール、 Angular1 をインストールします。

$ npm install -S @angular/common @angular/compiler @angular/core @angular/platform-browser @angular/platform-browser-dynamic @angular/upgrade
$ npm install -S reflect-metadata rxjs zone.js
$ npm install -S angular

ビルドには Browserify と Babel を使います。 Angular2 を遣うための babel-reset-angular2 もインストールしておきます。

$ npm install -g browserify
$ npm install -D babel-preset-angular2 babel-preset-latest babelify

.bashrc も用意しておきます。

{
  "presets": [
    "latest",
    "angular2"
  ]
}

コンポーネント

Angular2 のコンポーネントを用意します。

// greeting.component.js

import { Component, Input } from '@angular/core';

@Component({
    selector: 'my-greeting',
    template: '<div>Hello, {{name}}!</div>'
})
export class Greeting {
    @Input() name = 'World';
}

Hello, ???! と表示するだけのコンポーネントです。これを Angular 1 から使ってみます。

Angular

Angular2 以外の依存モジュールを最初に import しておきます。

import 'angular';
import 'reflect-metadata';
import 'zone.js';

次に Angular1 から使いたいコンポーネントを含んだモジュールを定義します。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { Greeting } from './greeting.component';

@NgModule({
    imports: [BrowserModule],
    declarations: [Greeting]
})
class AppModule {}

そのモジュールから UpgradeAdapter を作ります。

import { UpgradeAdapter } from '@angular/upgrade';

const adapter = new UpgradeAdapter(AppModule);

adapter.downgradeNg2Component メソッドで Angular2 のコンポーネントを Angular1 の directive に変換できます。Angular1 のモジュールに、それを加えれば Directive として使えるようになります。

const module = angular.module('app', []);

module.directive('myGreeting', adapter.downgradeNg2Component(Greeting));

UpgradeAdapter を使う場合は ng-app は使わずブートストラップのコードを書く必要があるみたいなので、それも書いておきます。

document.addEventListener('DOMContentLoaded', () => {
    adapter.bootstrap(document.body, ['app']);
}, false);

この JavaScript を app.js として保存したら Browserify でビルドします。

$ browserify -t babelify -o bundle.js app.js

できた bundle.js を使うHTMLが以下になります。

<!DOCTYPE html>
<meta charset="utf-8">
<script src="bundle.js"></script>
<body>
    <my-greeting></my-greeting>
    <my-greeting name="Taki"></my-greeting>
    <my-greeting name="Mitsuha"></my-greeting>
</body>

これを Web ブラウザで開くと Hello, 〜 と表示されます。

まとめ

  • UpgradeAdapter#downgradeNg2Component メソッドで Angular2 のコンポーネントを Angular1 のディレクティブに変換できる
  • その場合 UpgradeAdapter#bootstrap でブートストラップする必要がある