2016-03-28 4 views
0

コードスニペットでは、common.scriptディレクティブを使用して、付属のテンプレートapp/foo.htmlで定義されているコントローラFooCtrlを使用しようとしています。付属のテンプレートで定義されたコントローラを使用する

angular.module('common.script', []).directive('script', function() { 
 
    return { 
 
    restrict: 'E', 
 
    scope: false, 
 
    compile: function(element, attributes) { 
 
     if (attributes.script === 'lazy') { 
 
     var code = element.text() 
 
     new Function(code)() 
 
     } 
 
    } 
 
    } 
 
}) 
 
angular.module('app.templates', ['app/foo.html']) 
 
angular.module("app/foo.html", []).run(function($templateCache) { 
 
    $templateCache.put("app/foo.html", 
 
    "<script data-script=\"lazy\">\n" + 
 
    " console.log('Before FooCtrl')\n" + 
 
    " \t angular.module('app').controller('FooCtrl', function($scope) {\n" + 
 
    " \t \t console.log('FooCtrl')\n" + 
 
    " \t })\n" + 
 
    "<\/script>\n" + 
 
    "<div data-ng-controller=\"FooCtrl\">app\/foo.html\n" + 
 
    "<\/div>" 
 
) 
 
}) 
 
angular.module('app', ['common.script', 'app.templates']).controller('ApplicationCtrl', function($scope) { 
 
    console.log('ApplicationCtrl') 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script> 
 
<div data-ng-app="app" data-ng-controller="ApplicationCtrl"> 
 
    <div data-ng-include="'app/foo.html'"></div> 
 
</div>

しかし、その代わりに、コンソールAngularJSで予想される出力FooCtrlの例外:

Error: [ng:areq] Argument 'FooCtrl' is not a function [...] 

私は理由を理解していません!例外がスローされる前にテンプレート内のコードが実行されるため、コントローラを定義する必要があります。どうすればそれを修正できますか?

答えて

0

ここでの本当の問題は、リソースの遅延読み込みです!このトピックについてはmaterialrelated postsのトンがあります。ここ

ソリューションは、拡張common.scriptディレクティブが考えられます。

'use strict' 

angular.module('common.script', []) 

.config(function($animateProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) { 
    angular.module('common.script').lazy = { 
    $animateProvider: $animateProvider, 
    $controllerProvider: $controllerProvider, 
    $compileProvider: $compileProvider, 
    $filterProvider: $filterProvider, 
    $provide: $provide 
    } 
}) 

.directive('script', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     modules: '=script' 
    }, 
    link: function(scope, element) { 
     var offsets = {}, code = element.text() 

     function cache(module) { 
     offsets[module] = angular.module(module)._invokeQueue.length 
     } 

     function run(offset, queue) { 
     var i, n 
     for (i = offset, n = queue.length; i < n; i++) { 
      var args = queue[i], provider = angular.module('common.script').lazy[args[0]] 

      provider[args[1]].apply(provider, args[2]) 
     } 
     } 

     if (angular.isString(scope.modules)) { 
     cache(scope.modules) 
     } else if (angular.isArray(scope.modules)) { 
     scope.modules.forEach(function(module) { 
      cache(module) 
     }) 
     } 

     /*jshint -W054 */ 
     new Function(code)() 

     Object.keys(offsets).forEach(function(module) { 
     if (angular.module(module)._invokeQueue.length > offsets[module]) { 
      run(offsets[module], angular.module(module)._invokeQueue) 
     } 
     }) 
    } 
    } 
}) 

このソリューションの唯一の欠点は、あなたがscriptタグに拡張するモジュール(複数可)を指定する必要があることです。

<script data-script="'app'"> 
    angular.module('app').controller('FooCtrl', function($scope) { 
    console.log('Works!') 
    }) 
</script> 
関連する問題