注入动态html似乎无法编译

时间:2015-10-19 12:31:06

标签: angularjs

我正在尝试使用angularJS解决我在使用动态添加的包含ng-controller的html时遇到的一个主要问题。

让我们说我想在一个ng-controller的DOM中添加一个div,它将绑定数据脱离显示。我可以成功实现如下:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
    <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
        var demoData = {
            'test1': 'one',
            'test2': 'two'
        };

        var myApp = angular.module('myApp', []);
        myApp.controller('TestCtrl', function ($scope) {
            $scope.demo = demoData;
        });
    </script>
</head>
<body>
    <div ng-controller="TestCtrl">
        {{demo}}
    </div>            
</body>
</html>

按预期输出以下内容:

  

{ “测试1”: “一个”, “TEST2”: “2”}

但是,现在可以说div实际上必须动态加载,也许当用户按下按钮时。在这种情况下,我将使用以下内容替换上例中的标记:

<body>
    <button onclick="addDiv();">Click to add Div!</button>
    <script>
        function addDiv() {
            var newDiv = $('<div ng-controller="TestCtrl">{{demo}}</div>');
            $(document.body).append(newDiv);
        }
    </script>
</body>

单击按钮时输出以下内容:

  

点击添加Div!
  {{演示}}

到目前为止,这是有道理的; angular已经在DOM中完成了它的工作,完成了它。它没有被告知有关新内容的添加。 因此,如果我们查看AngularJS手册,就在this page的底部,我们会发现如何告诉它我们刚刚添加了一些内容:

  

有时您想要访问当前的注入器   从Angular外部运行Angular应用程序。也许,你想要注射   并在应用程序引导后编译一些标记。   您可以使用添加到JQuery / jqLit​​e的额外注入器()来完成此操作   元素。见angular.element。

     

这种情况相当罕见,但如果是第三方图书馆则属于这种情况   注入标记。

     

在以下示例中,包含一个新的HTML块   ng-controller指令被添加到文档正文的末尾   JQuery的。然后我们编译并将其链接到当前的AngularJS范围。       var $ div = $('{{content.label}}');       $(document.body的).append($ DIV);

angular.element(document).injector().invoke(function($compile) {
  var scope = angular.element($div).scope();
  $compile($div)(scope);
});

所以......考虑到这一点,我们在示例中更新了addDiv()函数,如下所示:

function addDiv() {
    var $newDiv = $('<div ng-controller="TestCtrl">{{demo}}</div>');
    $(document.body).append($newDiv);

    angular.element(document).injector().invoke(function ($compile) {
        var scope = angular.element($newDiv).scope();
        $compile($newDiv)(scope);
    });
}

现在当我们运行它时,我们应该是金色的吗? 不,我们仍然得到以下内容:

  

点击添加Div!
  {{演示}}

sad panda is sad

你能指出我做错了什么,因为谷歌搜索和阅读手册没有结束,因为一切似乎都表明我的代码是正确的!

2 个答案:

答案 0 :(得分:6)

您的代码与从 Angular ng-click调用的函数调用时的工作方式相同。

由于您似乎真的想避免使用Angular,因此需要传统的onclick事件处理程序,因此您需要将更改包装到对$scope.$apply()的调用中:http://plnkr.co/edit/EeuXf7fEJsbBmMRRMi5n?p=preview

angular.element(document).injector().invoke(function ($compile, $rootScope) {
    $rootScope.$apply(function() {
        var scope = angular.element($newDiv).scope();
        $compile($newDiv)(scope);
    });
});

答案 1 :(得分:3)

当你的变量是$ newDiv?

时,你是否正在尝试编译newDiv?

编辑:我认为这是因为您正在使用注入器并在角度控制器之外进行编译。

我在http://plnkr.co/edit/utQvgyR7d0jBgx5aEpJa?p=preview设置了一个plunkr来证明这一点。

该示例在页面正文中使用控制器:

app.controller('InitialController', function ($scope, $injector){
    $scope.newBtn = function () {
      var $newDiv = $('<div ng-controller="TestCtrl">{{demo}}</div>');

      $injector.invoke(function ($compile) {
          var div = $compile($newDiv);
          var content = div($scope);
          $(document.body).append(content);
      });
    };
});

这负责动态添加内容并使用第二个控制器编译该内容:

app.controller('TestCtrl', function($scope) {
  $scope.demo = "This is the div contents";
});

第二个控制器负责与该内容相关的逻辑。