albatrosary's blog

UI/UXとエンタープライズシステム

ngComponentRouterを利用する

Angular1.5もrcがとれて正式リリースされました。Angular1.5にはAngular2に繋がるComponentが実装されていてComponentRouter(New Routerと呼ばれていたもの)も利用可能になります。早速使ってみました。

準備

index.htmlの作成

必要なファイルとパッケージを作成します。

mkdir ComponentRouterSample && cd $_

ComponentRouterSampleの中にindex.htmlを生成します。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <base href="/">
  <title>Component Router Sample</title>
</head>
<body>
  
</body>
</html>

ライブラリの登録

npmを使って必要なライブラリを登録

npm init -y
npm i angular@1.5.0 --save
npm i ngcomponentrouter --save

ngComponentRouterに関するものは下記を見て下さい

New router · Issue #12926 · angular/angular.js · GitHub

GitHub - excellalabs/ngComponentRouter: Angular 2 Component Router for Angular 1

※ ngcomponentrouterはnpm install @angular/routerでも可(むしろこっち?)

モジュールの読み込み

Angular1.5とルーターを読み込ませ、ng-link, ng-outletの設定を行います。

<body ng-app="Sample" ng-controller="AppController as Sample">
  <ul>
    <li><a ng-link="['Home']">Home</a></li>
    <li><a ng-link="['About']">About</a></li>
  </ul>
      
  <div ng-outlet></div>
  
  <script src="node_modules/angular/angular.js"></script>
  <script src="node_modules/ngcomponentrouter/angular_1_router.js"></script>

  <!-- Components -->

</body>

SPAのためのコンポーネントを実装します。

  <!-- Components -->
  <script>
  angular
    .module('Sample', [
      'ngComponentRouter'
    ])
    .config(AppConfig)
    .controller('AppController', AppController)
    .component('homeController', {
      controller: function () {},
      template: '<h1>Home</h1>'
    })
    .component('aboutController', {
      controller: function () {},
      template: '<h1>About</h1>'
    });
  
  AppConfig.$inject = ['$locationProvider'];
  function AppConfig($locationProvider) {
    $locationProvider.html5Mode(true);
  }
  
  AppController.$inject = ['$router'];
  function AppController ($router) {
    $router.config([
      {path: '/home',    name:'Home',    component: 'homeController', useAsDefault: true},
      {path: '/about',   name:'About',   component: 'aboutController'}
    ]);
  }
  </script>

ルーティングの設定はAngular2とまったく同じです。実はこれだと動きません。

動くようにする

プルリクを送ろうと色々調べていたら本体に変更が入るようです。現状のソースを見るとルーティングは

(angular_1_router.js - L145)

this.controller.$$template = '<div ' + dashCase(componentName) + '></div>';

Angular1.5本体は

(angular/angular.js - L7611)

restrict: 'E',

Componentを、ルーティングでは属性として指定していて本体では要素として指定しているからです。最新のソースを見ると

本体が

restrict: options.restrict || 'E'

と変わっているため、最新の(まだリリースされていない)Angular本体を部分的に取り込み、コンポーネントの実装を次のように変えます。

    .component('homeController', {
      restrict: 'A',
      controller: function () {},
      template: '<h1>Home</h1>'
    })
    .component('aboutController', {
      restrict: 'A',
      controller: function () {},
      template: '<h1>About</h1>'
    });

完了。コンポーネントは

(angular_1_router.js - L145)

this.controller.$$template = '<' + dashCase(componentName) + '></' + dashCase(componentName) + '>';

の方がいいのではとも思いますが。。github上のissueでも「ミスった!」というのような話もあるので、もしかするとルーターの方が変わるかもしれません。

完成されたサンプルコードはこちらを見てください。

GitHub - albatrosary/ComponentRouter4Angular1: Angular1.5 and ngComponentRouter Sample