ngRepeat不更新自定义元素指令

时间:2015-01-27 16:43:20

标签: angularjs angularjs-directive

我有一个自定义元素指令(restrict: "E"),它用一个取决于范围的新元素替换自定义元素(通过处理link)。这工作正常,但ngRepeat无法删除此类指令。它似乎无法找到目标DOM元素,因为它已被指令本身取代。

代码:

<body ng-app="app">
  <div ng-controller="controller">
    <h3>Click an element to remove it</h3>
    <custom ng-repeat="tag in tags" ng-click="remove(tag)"></custom>
  </div>

  <script>
    angular.module("app", []).controller("controller", function($scope) {
      $scope.tags = [
        { tagName: "button", text: "button" },
        { tagName: "div", text: "div" },
        { tagName: "span", text: "span" }
      ];

      $scope.remove = function(tag) {
        console.log("remove", tag.text);
        $scope.tags.splice($scope.tags.indexOf(tag), 1);
      }
    }).directive("custom", function($compile) {
      return {
        restrict: "E",        
        link: function(scope, element, attr) {
          var tag = angular.element("<" + scope.tag.tagName + ">").text(scope.tag.text);

          tag.attr("ng-click", attr.ngClick)

          $compile(tag)(scope);

          element.replaceWith(tag);
        }
      }
    });
  </script>
</body>

Live demo(尝试点击button,然后div - 按钮首先不会消失,然后div和按钮都会消失)。如果我使用element.replaceWith(tag)代替element.append(tag),它就可以使用。

这可以以某种方式工作吗?我需要该指令具有取决于范围的自定义标记名称,并且在删除项目时也使用ngRepeat。长话短说我不需要DOM中的<custom>元素,因为我无法控制CSS规则。 replace:true之类的内容适用于link

2 个答案:

答案 0 :(得分:1)

要回答我自己的问题,是的,有可能使用transclude: 'element'。然后angular给link函数一个注释DOM元素,稍后它用于DOM操作。以下是相关代码:

  return {
    restrict: "E",
    transclude: "element",
    link: function(scope, element, attr) {
      var tag = angular.element("<" + scope.tag.tagName + ">").text(scope.tag.text);

      tag.attr("ng-click", attr.ngClick)

      $compile(tag)(scope);

      element.after(tag); // insert after the comment node
    }

live demo

答案 1 :(得分:0)

为什么需要更换?

 element.append(tag);

似乎work ok

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.11/angular.js" data-semver="1.3.11"></script>
    <script src="app.js"></script>
  </head>

<body ng-app="app">
  <div ng-controller="controller">
    <h3>Click an element to remove it</h3>
    <custom ng-repeat="tag in tags" ng-click="remove(tag)"></custom>
    <br><br>{{tags}}  
  </div>

  <script>
    angular.module("app", []).controller("controller", function($scope) {
      $scope.tags = [
        { tagName: "button", text: "button" },
        { tagName: "div", text: "div" },
        { tagName: "span", text: "span" }
      ];

      $scope.remove = function(tag) {
        console.log("remove", tag.text);
        $scope.tags.splice($scope.tags.indexOf(tag), 1);
      }
    }).directive("custom", function($compile) {
      return {
        restrict: "E",        
        link: function(scope, element, attr) {
          var tag = angular.element("<" + scope.tag.tagName + ">").text(scope.tag.text);

          tag.attr("ng-click", attr.ngClick)

          $compile(tag)(scope);

          element.append(tag);
        }
      }
    });
  </script>
</body>

</html>