2015-03-19 51 views
0

我想要在我的應用程序中創建一個插件系統。 在我的第一個版本中應該有一個插件文件夾,我把我的插件放在他們自己的文件夾中。AngularJS指令在預鏈接中等待諾言

每個插件都有自己的指令,應該在運行時加載。

的文件夾結構如下所示:

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

所以,主要的問題是,我想預裝插件指令的預鏈接過程中的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函數之前,有沒有辦法在plugin僞指令的prelink-function中等待loadScript-method?

回答

0

我會提出這種黑客攻擊。

由於範圍兩個功能(前,後)之間共享的,爲什麼不把它負載的承諾,然後等待它來解決:

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); 
      }); 
     } 
     } 
    }