2016-03-28 3 views
0

В фрагменте кода я пытаюсь использовать контроллер FooCtrl, который определен в включенном шаблоне app/foo.html с использованием директивы common.script.Использование контроллера, указанного в включенном шаблоне

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>

Но вместо ожидаемого результата FooCtrl в консольных AngularJS бросает:

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

Я не понимаю, почему! Код в шаблоне выполняется до генерирования исключения, поэтому контроллер должен быть определен. Как я могу это исправить?

ответ

0

Настоящая проблема здесь - это ленивая загрузка ресурсов! Есть тонны material и related 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>