在$ compile下更改HTML时,ng-repeat不起作用

时间:2017-02-19 12:05:45

标签: javascript angularjs angularjs-directive angularjs-ng-repeat

指令代码:

.directive('replace', function($compile) {
      return function (scope, element) {
        element.html(element.html().replace("Hej", "Hey!"));
        $compile(element.contents())(scope);
      }
  });
})

HTML

 <div ng-controller="GreeterController">
     <div replace>Hej <div ng-repeat="e in arr">{{ e }}</div>
     </div>
 </div>

控制器

app.controller('GreeterController', ['$scope', function($scope) {
    $scope.arr = [1, 2, 3, 4];
}]);

Live example

正如标题所说,当我在包含它的HTML上使用上面的指令时,ng-repeat无法正常工作。 但是,一旦我删除了使用.replace()命令替换部分HTML的行,那么ng-repeat由于某种原因开始工作。
有谁知道实际问题在哪里? 我已经尝试了一切,但我似乎仍然无法理解为什么它不能正常工作。

3 个答案:

答案 0 :(得分:0)

您应该让Angular及其更改检测周期为您执行HTML操作,而不是直接自行更改。

我已编辑您的示例以使用范围绑定来实现您想要的目标:

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example - example-compile-production</title>
  

  <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
  

  
</head>
<body ng-app="compileExample">
  <script>
  angular.module('compileExample', [], function($compileProvider) {
    // configure new 'compile' directive by passing a directive
    // factory function. The factory function injects the '$compile'
    $compileProvider.directive('replace', function($compile) {
        return {
            link: function (scope, element) {
              scope.greeting = 'Hey!';
              $compile(element.contents())(scope);
            }
        }
    });
  })
  .controller('GreeterController', ['$scope', function($scope) {
    $scope.test = [1, 2, 3, 4];
    $scope.greeting = 'Hej';
  }]);
</script>
<div ng-controller="GreeterController">
  <div replace>{{greeting}} <div ng-repeat="e in test">{{ e }}</div></div>
</div>
</body>
</html>

<!-- 
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->

注意:我删除了“scope:false”,因为这是默认行为。

编辑: 既然你必须替换HTML,这里是jQuery的解决方案:

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example - example-compile-production</title>
  

  <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
  <script
  src="https://code.jquery.com/jquery-3.1.1.min.js"
  integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
  crossorigin="anonymous"></script>

  
</head>
<body ng-app="compileExample">
  <script>
  angular.module('compileExample', [], function($compileProvider) {
    // configure new 'compile' directive by passing a directive
    // factory function. The factory function injects the '$compile'
    $compileProvider.directive('replace', function($compile) {
        return function (scope, element) {
          $(element).find( ".translation" ).replaceWith("Hey!");
        }
    });
  })
  .controller('GreeterController', ['$scope', function($scope) {
    $scope.arr = [1, 2, 3, 4];
  }]);
</script>
<div ng-controller="GreeterController">
  <div replace><span class="translation">Hej</span> <div ng-repeat="e in arr">{{ e }}</div></div>
</div>
</body>
</html>

<!-- 
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->

答案 1 :(得分:0)

解决这个问题:

.directive("replace", function(){
    return {
        compile: function(){
            return {
                pre: function(scope, element){
                    element.html(element.html().replace('Hej', 'Hey!'));
                }
            }
        }
    };
});

Live example

答案 2 :(得分:0)

操作也可以在编译阶段完成:

app.directive("replace", function(){
    return {
        compile: function(element){
            element.html(element.html().replace('Hej', 'Hey!'));
            /*return {
                pre: function(scope, element){
                  element.html(element.html().replace('Hej', 'Hey!'));
                }
            }*/
        }
    };
});

原始问题是由于ng-repeat指令的链接在具有该指令的元素被替换为替换操作之前完成的。然后,与ng-repeat指令关联的观察者对不再附加到可见DOM的元素进行操作。

通过将替换操作移动到编译阶段或preLink阶段,在ng-repeat指令链接之前替换具有ng-repeat指令的元素。与ng-repeat指令关联的观察者然后使用替换的DOM。