Javascript 如何通过工厂创建/编译指令?

Javascript 如何通过工厂创建/编译指令?,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我正在建立一个模态工厂,并且在$compile的问题上不断遇到难题。我正在尝试使用工厂向页面动态添加模态指令 指令本身有一些内部逻辑,允许它通过API服务发布来打开。它在其postLink中向发布/订阅服务注册,如下所示: postLink: function(scope, element, attrs) { api.subscribe(attrs.id, function(msg) { //magic happens here }); } 工厂创建并附加指令,如下所示:

我正在建立一个模态工厂,并且在
$compile
的问题上不断遇到难题。我正在尝试使用工厂向页面动态添加模态指令

指令本身有一些内部逻辑,允许它通过API服务发布来打开。它在其
postLink
中向发布/订阅服务注册,如下所示:

postLink: function(scope, element, attrs) {

  api.subscribe(attrs.id, function(msg) {
    //magic happens here
   });
}
工厂创建并附加指令,如下所示:

angular.module('modal')
  .factory('ModalFactory', ['$compile', '$rootScope', 'Api', function($compile, $rootScope, api) {
    return function modalFactory(config) {
      var scope, element, html, id;

      init(); //run init so it's initialized on creation

      function activate() {
        api.publish(id, 'activate');
      }

      function init() {
        //checks if initialized already
        //uses assembleDirective to get the html string and scope

        angular.element(document.body).append($compile(html)(scope)); //this is the important line of code
      }


     function assembleDirective() {
      //an html string is assembled here and stored into html. uses html from config

      //rootscope is used to create a new scope (unless provided in config) 
     }     

      return {
        activate: activate,
        deactivate: deactivate
      }
    }

}]);
问题是,每当我在控制器中运行此逻辑时,如下所示:

//imagine we're in a controller
var myModal = new ModalFactory({ }); //create empty modal
myModal.activate(); //fails
问题出在哪里?当我运行
myModal.activate()
时,由于某种原因,该指令尚未运行任何内部链接逻辑。I console.log退出进程,激活方法在指令本身运行链接之前运行。这让我大吃一惊,因为我认为我刚刚编译了它并将其添加到DOM中(当我想到编译时,我想到的是运行前/后链接函数)

当我登录控制台
$compile(html)(scope)
时,它返回一个jQLite元素,其中包含编译的所有内容,这使我认为它工作正常。但是,当我从jQLite对象中获得实际的DOM片段时(通过最后执行
[0]
),我得到了原始HTML字符串的DOM表示,uncompiled


当我将一个单独的方法附加到控制器上,该控制器在单击时运行
myModal.activate()
,该指令已经运行了它的链接方法,并且该模式被激活。

我相信您的问题是,在DOM周围移动角度元素会导致内部带有角度的螺钉。安全的方法是先附加它,然后编译。两者之间的时间间隔将很小。如果这样更改代码,是否会遇到问题

  function init() {
    //checks if initialized already
    //uses assembleDirective to get the html string and scope
    var modalElt = angular.element(document.body).append(html);
    $compile(modalElt)(scope);
  }
也许可以查看Brian Ford的angular modal中的代码:


找一行$compile

对于仔细阅读这个问题的人,我最终找到了一个答案,首先Peter的建议帮了大忙(在添加元素后编译)


我最后做的是在编译之前在作用域上设置属性。该属性在postLink的模式中启动了一个
init
函数,因此
$compile
的异步性质最终并不重要。

您的api服务是如何工作的?你怎么称呼init?你是否处于摘要周期中?API是一个简单的发布/订阅系统。所以我尝试了你的解决方案,结果导致Chrome崩溃。我认为你的建议会编译整个身体,可能会陷入无限循环。我查看了angular modal代码,发现他没有编译文档的整个主体,而是在添加文档之后编译了他所附加的内容,如果这有意义的话。这个解决方案仍然不起作用,因为我认为$compile是异步的,这就是我遇到麻烦的地方。对不起,我认为append函数刚刚返回了模态的HTML——这正是我想要的。很高兴它对你有帮助。我不应该那么可爱