LoginSignup
25
26

More than 5 years have passed since last update.

[備忘録]angularjsでcontrollerを動的に追加する

Last updated at Posted at 2014-03-11

controllerをイベントによって、動的にロードしたいが、
angular.bootstrap()実行後に、app.controller('XXX')で、追加しても、
Error: [ng:areq] Argument 'XXX' is not a function, got undefined
となってしまう。

angular.config()で、controllerProviderを設定し、controllerProvider.register()で追加する。

●サンプル

下記、HTMLのHogeController#doClick()で動的にエレメントを追加し、
その中のボタンを押した時に、イベントを発生させる。

index.html
<!DOCTYPE html>
<html lang="ja" >
  <head>
    <meta charset="utf-8">

    <title>angular test 1</title>
    <script src="dist/js/lib/jquery/jquery-2.1.0.js"></script>
    <script src="dist/js/lib/angularjs/angular.js"></script>
    <script src="dist/js/app/main.js?hoge"></script>

  </head>

  <body>
    <div ng-controller="HogeController as HogeC">
      <button type="button"  ng-click="HogeC.doClick()" >click</button>
    </div>
    <div>hello</div>
    <div>
      <testWidget/>
    </div>

  </body>
</html>

testWidgetに追加するエレメントは、下記。
ボタンクリックのイベントを実行する為に、FugaControllerを動的に追加する。

<testWidgetSub ng-controller='FugaController'>
  <div >tttt
   <button type='button'ng-click='doFuga()'>Fuga!</buffon>
  </div>
</testWidgetSub>

ロードするJSは以下。

main.js

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

app.controller('HogeController' ,[
    '$scope', '$compile', 
    function($scope ,$compile ) {

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

            var elm = angular.element('testWidget testWidgetSub');
            console.log(elm.size());


            if (elm.size() == 0) {
            // エレメントが、まだ、追加されてない場合

                // コントローラーを追加
                app.controllerProvider.register('FugaController', [
                    '$scope', '$compile',
                    function($scope ,$compile) {
                            $scope.doFuga = function() {
                                // fugaボタンを押した時のイベント
                                console.log('fuga controller clicked!!!');
                            };
                    }
                ]);

                var hoge = $compile("<testWidgetSub ng-controller='FugaController'><div >{{'tttt'}}<button type='button'ng-click='doFuga()'>Fuga!</buffon></div></testWidgetSub>")($scope);

                // 作ったエレメントのコンパイル
                app.directive('testWidgetSub' ,
                              function(scope) {
                                  scope.$apply();
                              });

                // エレメント追加                
                angular.element('testWidget').append(hoge);
                console.log('append testWidgetSub on testWidget!!!!!');
            } else {
                console.log('already append testWidgetSub....');
            }
        } 

    }
]);

// DOMのロード完了時に実行しないと、Chromeでエラーになる場合がある
// なので、とりあえず、jqueryで、angular.bootstrap()を、実行...
$(function() {
    // providerを登録
    app.config(function($controllerProvider, $compileProvider, $filterProvider, $provide)
    {
        app.controllerProvider = $controllerProvider;
        app.compileProvider    = $compileProvider;
        app.filterProvider     = $filterProvider;
        app.provide            = $provide;
    });

    // bootstrap実行
    angular.bootstrap(document, ['app']);

    console.log("angular bootstrapped...");

});

angular.module('app')宣言後、bootstrap前に、app.configを実行し、controllerProviderを設定する。
bootstrap後、controllerの定義は、controllerProvider.register()で行う。

25
26
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
25
26