【问题标题】:How to replace an element in AngularJS directive linking function?如何替换 AngularJS 指令链接函数中的元素?
【发布时间】:2013-06-10 01:38:44
【问题描述】:

我正在创建一个<row> AngularJS 指令,该指令需要用可以包含任何 HTML 代码的动态模板替换自身(<row> 标记在执行后不能出现在 DOM 中)。

使用replace: true 的问题在于它不适用于表格的<tr> 标签,并且模板是动态选择的。

所以我试图找到一种方法来替换链接函数中的元素,但没有成功。

使用 jQuery 的 .replaceWith() 会因未知原因中断 ngRepeat

有什么提示吗?

这里是fiddle

【问题讨论】:

  • 你能提供一个你尝试过的东西吗?更容易看到然后尝试从您的描述中辨别。
  • 我认为这个问题没有解决方案,因为替换 ,它持有 ng-repeat 显然会破坏 ng-repeat!

标签: jquery dom angularjs angularjs-directive


【解决方案1】:

Mark 的回答会起作用,但是,该示例过于有限,无法显示整个画面。虽然 Mark 的指令对于常见和简单的 UI 组件可能确实足够,但对于更复杂的操作,该模式是一种应该避免的模式。下面我详细说明这背后的原因。事实上,Angular已经提供了一种更简单的方法来用模板替换指令元素。它可以在这个答案的底部找到。

下面是指令在幕后的样子:

.directive('row', function ($compile) {
  return {
      restrict: 'E',
      scope: {
          items: "="
      },

      // Whether you define it this way or not, this is the order of
      // operation (execution) behind every AngularJS directive.
      // When you use the more simple syntax, Angular actually generates this
      // structure for you (this is done by the $compile service):

      compile: function CompilingFunction($templateElement, $templateAttributes, transcludeFn) {

        // The compile function hooks you up into the DOM before any scope is
        // applied onto the template. It allows you to read attributes from
        // the directive expression (i.e. tag name, attribute, class name or
        // comment) and manipulate the DOM (and only the DOM) as you wish.

        // When you let Angular generate this portion for you, it basically
        // appends your template into the DOM, and then some ("some" includes
        // the transclude operation, but that's out of the $scope of my answer ;) )

          return function LinkingFunction($scope, $element, $attrs) {

            // The link function is usually what we become familiar with when
            // starting to learn how to use directives. It gets fired after
            // the template has been compiled, providing you a space to
            // manipulate the directive's scope as well as DOM elements.

            var html ='<div ng-repeat="item in items">I should not be red</div>';
            var e = $compile(html)($scope);
            $element.replaceWith(e);
          };
      }
  };
});

我们能从中得到什么?很明显,为相同的 DOM 布局手动调用 $compile两次 是多余的,对性能不利并且对您的牙齿也不利。你应该怎么做?只需在 应该 编译你的 DOM 的地方编译:

.directive('row', function ($compile) {
  return {
      restrict: 'E',
      template: '<div ng-repeat="item in items">I should not be red</div>',
      scope: {
          items: "="
      },

      compile: function CompilingFunction($templateElement, $templateAttributes) {
          $templateElement.replaceWith(this.template);

          return function LinkingFunction($scope, $element, $attrs) {
            // play with the $scope here, if you need too.
          };
      }
  };
});

如果您想深入了解指令,我喜欢称之为非官方AngularJS Directive Reference

一旦你完成了这里的那个头:https://github.com/angular/angular.js/wiki/Understanding-Directives


现在,正如承诺的那样,这是您来这里的解决方案:

使用replace: true

.directive('row', function ($compile) {
    return {
        restrict: 'E',
        template: '<div ng-repeat="item in items">I should not be red</div>',
        replace: true,
        scope: {
            items: "="
        }
    };
});

【讨论】:

  • 他们为什么不把它放在 Angular 页面的指令中呢? replace: true 是我在寻求指令时想做的第一件事。很棒的帖子。
  • 谢谢。即使在 1.3 版中,Angular 文档仍然低于标准,还有很多不足之处。此外,Google Groups 的选择(没有语法突出显示,甚至没有&lt;pre&gt; 标签)也很难理解。幸运的是我们有这样的:)
  • replace: true 已弃用,将在 Angular 1.2.0 中删除:docs.angularjs.org/api/ng/service/$compile#-templateurl-
  • Replace 在下一个主要版本之前不会被删除......以及其他所有内容。
  • @pilau 所以现在我知道为什么我的牙疼了 xD ...顺便说一句,答案很好!
【解决方案2】:

你的小提琴看起来很基础,但你应该可以使用outerHTML

element[0].outerHTML ='<div>I should not be red</div>';

Updated fiddle

如果您必须处理ng-repeat,您可以将您的项目绑定到范围属性并在您编译的模板中引用它们。编译完成后,您可以使用 jQuery replaceWith()

html

<row items="items">***</row>

指令

.directive('row', function ($compile) {
    return {
        restrict: 'E',
        scope: {
            items: "="
        },
        link: function (scope, element, attrs) {
            var html ='<div ng-repeat="item in items">I should not be red</div>';
            var e =$compile(html)(scope);
            element.replaceWith(e);
        }
    };
});

ng-repeat example

【讨论】:

    猜你喜欢
    • 2015-03-28
    • 2015-01-11
    • 2014-03-11
    • 2018-01-11
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 2015-07-16
    相关资源
    最近更新 更多