你如何通过工厂 create/compile 指令?

How do you create/compile a directive via a factory?

我正在建造一个 Modal 工厂,并且经常被 $compile 的问题难倒。我正在尝试使用工厂将 Modal 指令动态添加到页面。

指令本身有一些内部逻辑,允许它通过 API 服务发布来打开。它在 postLink 中将自己注册到 pub/sub 服务,如下所示:

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() 时,出于某种原因,指令还没有 运行 任何内部 linking 逻辑。我 console.logged 在指令本身 运行s link 之前 运行s 列出了过程和激活方法。这让我大吃一惊,因为我以为我刚刚编译它并添加到 DOM(当我想到编译时,我想到了 pre/post link 函数 运行宁)

当我在控制台记录 $compile(html)(scope) 时,它 returns 一个编译了 everything 的 jQLite 元素,这让我认为它工作正常。但是,当我从 jQLite 对象中得到 DOM 的实际部分时(通过在最后执行 [0] ),我得到了原始 HTML 的 DOM 表示字符串,未编译。

当我将一个单独的方法附加到点击时 运行s myModal.activate() 的控制器时,指令已经 运行 它的 link 方法并且模态被激活.

我相信你的问题是在 DOM 周围移动 angular 元素与 Angulars 内部构件。做你正在做的事情的安全方法是先附加它,然后编译。两者之间的时间间隔将很小。如果您这样更改代码,您会遇到问题吗?

  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 中的代码:

https://github.com/btford/angular-modal/blob/master/modal.js

寻找带有 $compile

的行

对于仔细阅读这个问题的任何人,我终于想出了一个答案,首先彼得的建议帮助很大(在追加元素后编译)。

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