我想在我的应用程序中创建一个插件系统。 在我的第一个版本中应该有一个插件文件夹,我将插件放在他们自己的文件夹中。
每个插件都有自己的指令,应该在运行时加载。
文件夹结构如下所示:
-plugins
--plugin1
---directive_plugin1.js
---plugin1.html
--plugin2
---directive_plugin2.js
---plugin2.html
在我的应用程序中,有一些注册的插件如下所示:
$rootScope.registered_plugins = ['plugin1', 'plugin2'];
所以我设置了一个插件指令,如下所示:
module.directive('plugin', ['$compile', 'angularLoad', function($compile, angularLoad) {
return {
restrict: 'E',
scope: { 'plugin': '@' },
compile: function(element, attrs, transclude) {
return {
pre: function preLink(scope, element, attrs, controller) {
console.log('PRE!');
var load_script = function() {
var url = '/js/plugins/' + scope.plugin + '/directive_' + scope.plugin + '.js';
var load = angularLoad.loadScript(url);
load.then(function () {
console.log('LOADED!');
});
load.catch(function () {
console.log('NOT LOADED!');
});
};
load_script();
},
post: function postLink(scope, element, attrs, controller) {
console.log('POST!');
var template = '<' + scope.plugin + ' />';
var compiled = $compile(template)(scope);
element.append(compiled);
}
}
}
}
}]);
我的插件工厂看起来像这样:
module.factory('pluginfactory', function ($q, $timeout) {
return function(key) {
var d = $q.defer();
$timeout(function() {
d.resolve(key);
}, 1);
return d.promise;
};
});
我的plugin1指令如下所示:
module.directive('plugin1', function() {
return {
restrict: 'E',
templateUrl: '/js/plugins/plugin1/plugin1.html'
};
});
我的plugin1 html看起来像这样:
<p>Hello, I am plugin1</p>
我的plugin2指令如下所示:
module.directive('plugin2', function() {
return {
restrict: 'E',
templateUrl: '/js/plugins/plugin2/plugin2.html'
};
});
我的plugin2 html看起来像这样:
<p>Hello, I am plugin2</p>
我的控制器看起来像这样:
module.controller('PluginController', function($scope, pluginfactory){
$scope.reset_loading();
$scope.templates = [
{template: {url: $scope.folder_plugin + '/plugin_content.html'}}
];
$scope.template_plugin_content = $scope.templates[0].template;
$scope.validated_plugins = [];
$scope.validate_plugins = function() {
for(var i = 0; i < $scope.registered_plugins.length; i++) {
var key = $scope.registered_plugins[i];
pluginfactory(key).then(function (plugin) {
$scope.validated_plugins.push(plugin);
});
}
};
});
我的插件html看起来像这样(它正在使用PluginController):
<div class="col2">
<div class="container-inner"
ng-init="validate_plugins()">
<h1>{{ 'PLUGIN_CONTENT' | translate }}</h1>
<div ng-repeat="p in validated_plugins">
<plugin plugin='{{ p }}'></plugin>
</div>
</div>
</div>
所以主要的问题是,我想在plugin指令的prelink过程中预加载plugin1和plugin2指令。我读到角加载应该对我有用。
当我执行代码时,插件的内容如下所示:
<div ng-repeat="p in validated_plugins" class="ng-scope">
<plugin plugin="plugin1" class="ng-isolate-scope"><plugin1 class="ng-scope"></plugin1></plugin>
</div>
<div ng-repeat="p in validated_plugins" class="ng-scope">
<plugin plugin="plugin2" class="ng-isolate-scope"><plugin2 class="ng-scope"></plugin2></plugin>
</div>
所以,基本上没有设置p元素。
角度加载在运行时产生的代码如下所示:
<script src="/js/plugins/plugin1/directive_plugin1.js"></script>
<script src="/js/plugins/plugin2/directive_plugin2.js"></script>
当我复制并粘贴代码中的两行并加载应用程序时,它可以正常工作。两个p元素都正确显示。
控制台日志向我显示:
directive_plugin.js:8 PRE!
directive_plugin.js:27 POST!
directive_plugin.js:8 PRE!
directive_plugin.js:27 POST!
2directive_plugin.js:15 LOADED!
所以我看到,问题是角度加载的异步函数。
在执行postLink函数之前,有没有办法在插件指令的preLink-function中等待loadScript-method?
答案 0 :(得分:0)
我会提出这种黑客行为。
由于范围是在两个函数(pre和post)之间共享的,为什么不在其中放置load promise并等待它解决:
compile: function(element, attrs, transclude) {
return {
pre: function preLink(scope, element, attrs, controller) {
console.log('PRE!');
var load_script = function() {
var url = '/js/plugins/' + scope.plugin + '/directive_' + scope.plugin + '.js';
// storing the promise in the scope
scope.isLoadedPromise = angularLoad.loadScript(url);
scope.isLoadedPromise.then(function() {
console.log('LOADED!');
}).catch(function() {
console.log('NOT LOADED!');
});
};
load_script();
},
post: function postLink(scope, element, attrs, controller) {
console.log('POST!');
// waiting for the loading to finish
scope.isLoadedPromise.then(function() {
console.log('YES IT IS LOADED!');
var template = '<' + scope.plugin + ' />';
var compiled = $compile(template)(scope);
element.append(compiled);
});
}
}
}