【问题标题】:injecting dynamic html doesn't seem to compile注入动态 html 似乎无法编译
【发布时间】:2015-10-19 12:31:06
【问题描述】:

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

假设我想在 DOM 中添加一个 div,它是一个 ng-controller,它会将绑定的数据脱口而出到显示器上。我可以通过以下方式成功实现:

<!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>

按预期输出以下内容:

{"test1":"one","test2":"two"}

但是,现在让我们说 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 指令被添加到文档正文的末尾 查询。然后我们编译并将其链接到当前的 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!
{{演示}}

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

【问题讨论】:

  • 你所有的问题都源于你试图像使用 jQuery 一样使用 AngularJS。您不应该使用 AngularJS 动态生成或加载 HTML。您应该以 JSON 格式加载数据。根据数据包含的内容,使用 ng-show、ng-if 和其他指令的静态模板应该显示/隐藏页面的部分。页面之间的导航应该使用路由器来完成。
  • 在 AngularJS 应用程序中,addDiv() 函数不应添加 div。它应该向存储在作用域中的数组添加一个元素。显示该数组所有元素的 ng-repeat 指令将检测新元素,并相应地刷新视图。
  • 我明白你在说什么,但这对我没有帮助,因为我无法真正重新设计我们的整个网络应用程序以以这种方式使用 Angular。我想要实现的只是在一个更大的网络应用程序中的少数动态加载页面中使用角度。如果您查看引用的 AngularJS 手册,它确实指出这应该是可能的?
  • 它会起作用的。只需对 url 使用 ng-repeat 迭代,然后 ng-include 视图中的每个 url。当你想添加一个 div 时,将一个 URL 添加到 URL 数组中。
  • @JBNizet - 抱歉 - 编辑了我之前的评论,以更好地解释我面临的问题。

标签: angularjs


【解决方案1】:

当从 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);
    });
});

【讨论】:

  • 并不是我想避免使用 Angular,而是我无法证明对现有产品的核心部分进行数周的编码和测试是合理的,然后实现可能需要半天时间才能完成的功能写。包含 $rootScope 是缺少的关键。只需添加即可使一切正常运行。感谢您的回答和帮助。
【解决方案2】:

当变量为 $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";
});

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

【讨论】:

  • 将此作为澄清问题添加到原始问题中,而不是作为答案。
  • @Matt 很遗憾没有。这只是问题中的错字,而不是我的代码。更新了问题以更正:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-14
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多