LoginSignup
11
12

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-03-12

●サンプル
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で書いたらスッキリ書けるかどうか調べる。

11
12
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
11
12