angularjsのcontrollerをrequirejsを使って動的にロードする


●サンプル
HogeControllerのボタンをクリックすると、requirejsでコントローラー、テンプレートを
ロードし、テンプレートの内容をtestWidgetに追加する。
追加した内容は、ロードしたコントローラーに紐づいてるので、
ボタンを押すと、ロードしたコントローラーのイベントが起動する。

[画面html]

```index.html
<!DOCTYPE html>
<html lang="ja" >
  <head>
    <meta charset="utf-8">
    <title>angular require test 1</title>
    <!-- requiejsのエントリ -->
    <script data-main="dist/js/app/boot.js?hoge" src="dist/js/lib/require.js"></script>
  </head>

  <body>
    <div ng-controller="HogeController as HogeC">
      <button type="button"  ng-click="HogeC.doClick()" >click</button>
    </div>
    <div>hello</div>
    <div>
      <testWidget>
        <!-- 上のボタンを押すとコントローラーをロードして、ここにテンプレートの内容を挿入する -->
      </testWidget>
    </div>

  </body>
</html>

```

[ボタンクリックでtestWidget挿入する内容のテンプレート]

```test_template.html
<testWidgetSub ng-controller='FugaController'>
  <div >{{'tttt'}}<button type='button' ng-click='doFuga()'>Fuga!</button></div>
</testWidgetSub>
```

[初期ロードjs]

```boot.js
require.config({
    paths: {
        'angular':           'lib/angularjs/angular'
        ,'jquery':           'lib/jquery/jquery-2.1.0'
        ,'app':              'app/app'
        ,'hoge_controller':  'app/hoge_controller_define'
        ,'fuga_controller':  'app/fuga_controller_define'
    }

    ,shim: {
        "angular":           {"deps": ["jquery"] ,"exports": "angular"}
        ,"app":              {"deps": ["angular"]}
        ,"hoge_controller":  {"deps": ["app"]}
        ,"fuga_controller":  {"deps": ["app"]}
    }

    ,baseUrl: 'dist/js'

    // cache防止
    ,urlArgs: 'bust=' + (new Date()).getTime()
});

require([
    'jquery' ,'angular' ,'app' ,'hoge_controller'
], function(jQuery ,angular ,app) {

    console.log('boot app start.');

    // DOMロード時、実行
    $(function() {
        angular.bootstrap(document, ['app']);
        console.log("boot app end.");
    });
});
```

[angularアプリ設定js]

```app.js
define([
    'angular' ,
    'jquery' 
], function (angular ,jQuery) {

    // angularアプリケーションの初期化
    var app = angular.module('app' ,[]);
    // bootstrap後にcontrollerを追加出来るよう、controllerProvider設定
    app.config(function($controllerProvider, $compileProvider, $filterProvider, $provide)
    {
        app.controllerProvider = $controllerProvider;
        app.compileProvider    = $compileProvider;
        app.filterProvider     = $filterProvider;
        app.provide            = $provide;
    });

    return app;
});
```

[angularコントローラーjs]

```hoge_controller_define.js
define([
    'angular',
    'jquery',
    'app'
], function (angular ,jQuery ,app) {

    // HogeController定義
    // このコントローラーは、angular.bootstrapまでに読み込まれる。
    // なので、コントローラーの定義は、controller()で行う。
    app.controller('HogeController' ,[
        '$scope', '$compile', '$http',
        function($scope ,$compile ,$http) {

            this.doClick = function() {
                console.log('click');

                // testWidgetに追加されてない場合、ロードして追加。
                var elm = angular.element('testWidget testWidgetSub');
                if (elm.size() == 0) {

                    // FugaControllerを動的にロード
                    require([
                    'jquery' ,'angular' ,'app' ,'fuga_controller'
                    ], function(jQuery ,angular ,app) {

                        // テンプレートを動的にロード
                        $http.get('dist/template/test_template.html')
                            .success(
                                function(data,status,headers,config) {

                                    // ロードしたテンプレートをコンパイルして
                                    // testWidgetに追加
                                    var hogeViewTmpl = $compile(data)($scope);
                                    app.directive('testWidgetSub' ,
                                                  function(scope) {
                                                      scope.$apply();
                                                  });
                                    angular.element('testWidget').append(hogeViewTmpl);

                                })
                            .error(
                                function(data,status,headers,config) {
                                    console.log('load template failed .');
                                }
                            );

                    });

                }

            } 
        }
    ]);

    // angular.bootstrap()してないので、
    // angular.controller('HogeController')は返せない...
    return app;
});
```

[angularコントローラーjs（bootstrap後）]

```fuga_controller_define.js
define([
    'angular',
    'jquery',
    'app'
], function (angular ,jQuery ,app) {

    // FugaController定義
    // このコントローラーは、HogeController.doClickのイベントで読み込まれる。
    // なので、コントローラーの定義は、controllerProvider.register()で行う。
    app.controllerProvider.register('FugaController', [
        '$scope', '$compile', '$http',
        function($scope ,$compile ,$http) {
            $scope.doFuga = function() {
                console.log('fuga controller clicked!!!');
            };
        }
    ]);

    return app.controller('FugaController');
});
```

●雑感
結構メンドクサイ処理になった。
最初から全部読み込んどく事、前提なのかな？
沢山画面あって階層型にする時でも、SPAでは、全部、読み込んどくベキなんだろうか？


●[TODO]
サービスについて調べてないけど、やっぱりプロバイダが必要？

require.configのpathsを後で追加出来るか調べる
（出来ない、もしくは、とてもメンドクサイ処理になりそう
　→※require時、パスを指定して拡張子を付ければ読み込むが、イマイチ...）

$http.getをangularモジュールの外部から呼べないか調べる
　→テンプレート取得のタイミングを変えたい

backboneで書いたらスッキリ書けるかどうか調べる。