jquery - AngularJS - 无法在链接函数中动态更改指令模板

标签 jquery angularjs templates angularjs-directive promise

小心

接受的解决方案将破坏带有 replace: true 的指令:HTML 将不会被替换,正在使用的特定 CSS 选择器将不再起作用,等等。

<小时/>

我希望我的指令通过观察从父 Controller 作为属性接收的字符串来动态更改其模板,因此我使用了 this answer 中的 $compilethis small part of an interesting tutorial 中的 $observe 一起使用,但是它不起作用,如this plunkr所示.

关于错误

如果脚本中 AngularJS 之前包含 jQuery,则 replaceWith 调用会抛出以下错误:

TypeError: Cannot read property 'ownerDocument' of undefined

但是如果我删除 jQuery,强制 AngularJS 使用它的 jqLit​​e,同一部分会抛出此错误,让像我这样完全不了解 jQuery 的人变得更清楚:

TypeError: Failed to execute 'replaceChild' on 'Node': parameter 1 is not of type 'Node'.

即使我很清楚我没有将有效的“Node”类型对象传递给 replaceWith,我也不知道如何处理这种情况,因为我期待 $compile 来完成这项工作。

我唯一知道的是 console.log(tplContent) 看起来像这样(我的 promise 是对的吗?):

Object
{
  config: Object
  data: "<script type="text/ng-template" id="templateId.html">
  ↵  <p>TEMPLATE A</p>
  ↵</script>"
  headers: function (d)
  ng339: 10
  status: 200
  statusText: "OK"
}

console.log($compile(tplContent)(scope)) 返回一个数组,该数组与第一个也是唯一一个项目具有相同的对象:

[Object]
0: {
  config: Object
  data: "<script type="text/ng-template" id="templateId.html">
  ↵  <p>TEMPLATE A</p>
  ↵</script>"
  headers: function (d)
  ng339: 10
  status: 200
  statusText: "OK"
},
length: 1

我确实想避免使用以下两个后备方案中的任何一个,您知道我在这里做错了什么吗?

<小时/>

后备又名不告诉我这样做

我知道我可以将指令拆分为两个指令,然后 ng-if 它们如下所示:

(function() {
  'use-strict';

  angular.module('app')
  .directive('dynamicTemplateA', dynamicTemplate);

  DynTplCtrl.$inject = ['$http', '$templateCache', '$compile', '$parse'];

  function dynamicTemplate($http, $templateCache, $compile, $parse) {
    var directive = {
      restrict: 'E',
      templateUrl: 'template-a.html',
      scope: {},
      bindToController: {
        tpl: '@',
        i: '='
      },
      controller: DynTplCtrl,
      controllerAs: 'dyntplctrl',
      link: linkFunc
    }

    return directive;

    function linkFunc(scope, el, attrs, ctrl) {}
  }

  DynTplCtrl.$inject = [];

  function DynTplCtrl() {}

})()

(function() {
  'use-strict';

  angular.module('app')
  .directive('dynamicTemplateB', dynamicTemplate);

  DynTplCtrl.$inject = ['$http', '$templateCache', '$compile', '$parse'];

  function dynamicTemplate($http, $templateCache, $compile, $parse) {
    var directive = {
      restrict: 'E',
      templateUrl: 'template-b.html',
      scope: {},
      bindToController: {
        tpl: '@',
        i: '='
      },
      controller: DynTplCtrl,
      controllerAs: 'dyntplctrl',
      link: linkFunc
    }

    return directive;

    function linkFunc(scope, el, attrs, ctrl) {}
  }

  DynTplCtrl.$inject = [];

  function DynTplCtrl() {}

})()

然后在controller.html中:

<div ng-repeat="i in [1,2,3]">
  <dynamic-template-a ng-if="mainctrl.tpl === 'a'" tpl="{{mainctrl.tpl}}" i="i"></dynamic-template-a>
  <dynamic-template-b ng-if="mainctrl.tpl === 'b'" tpl="{{mainctrl.tpl}}" i="i"></dynamic-template-b>
</div>

我也知道我可以使用ng-include like this :

(function() {
  'use-strict';

  angular.module('app')
  .directive('dynamicTemplateA', dynamicTemplate);

  DynTplCtrl.$inject = ['$http', '$templateCache', '$compile', '$parse'];

  function dynamicTemplate($http, $templateCache, $compile, $parse) {
    var directive = {
      restrict: 'E',
      template: '<div ng-include="dyntplctrl.getTemplateUrl()"></div>',
      scope: {},
      bindToController: {
        tpl: '@',
        i: '='
      },
      controller: DynTplCtrl,
      controllerAs: 'dyntplctrl',
      link: linkFunc
    }

    return directive;

    function linkFunc(scope, el, attrs, ctrl) {}
  }

  DynTplCtrl.$inject = [];

  function DynTplCtrl() {
    var vm = this;
    vm.getTemplateUrl = _getTemplateUrl;

    function _getTemplateUrl() {
      return 'template-' + vm.tpl + '.html';
    }
  }

})()

最佳答案

感谢 this question

在替换模板时,您需要稍微更改一下代码:

el.html(tplContent.data);
$compile(el.contents())(scope);

这将替换元素的内容(尽管您需要在此处处理清理),然后在指令的范围内编译模板。

此外,为了进行测试,我删除了 <script>来自 template-a.html 的标签,和template-b.html .

这是一个forked plunker其中有上述更改。

关于jquery - AngularJS - 无法在链接函数中动态更改指令模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43234325/

相关文章:

javascript - 如何停止 DOM 直到特定的 js 文件完全加载?

angularjs - Protractor - 下拉元素不可见(自动完成下拉)

c++ - 指向类成员的指针作为模板参数

javascript - jquery ui resizable防止高度小于文本

php - 如何通过ajax请求获取图片?

php - jquery 文件上传插件 : Can I set upload path at runtime?

javascript - angular.js 和 zurb foundation 显示模态

javascript - 使用 ng-options 过滤大写字母

c++ - 为什么我不能像使用 std::string::size_type 那样使用 QList::size_type? (模板参数错误)

c++ - 使模板类的用户独立于模板类型