AngularJS + JQuery:如何使动态内容在angularjs中工作


84

我正在使用jQuery和AngularJS开发Ajax应用程序。

当我使用jQuery的html功能更新div的内容(包含AngularJS绑定)时,AngularJS绑定不起作用。

以下是我正在尝试执行的代码:

$(document).ready(function() {
  $("#refreshButton").click(function() {
    $("#dynamicContent").html("<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>")
  });
});
</style><script src="http://docs.angularjs.org/angular-1.0.1.min.js"></script><style>.ng-invalid {
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="">
  <div id='dynamicContent'>
    <button ng-click="count = count + 1" ng-init="count=0">
        Increment
      </button>
    <span>count: {{count}} </span>
  </div>


  <button id='refreshButton'>
    Refresh
  </button>
</div>

我在具有ID的div中包含动态内容#dynamicContent,并且我具有一个刷新按钮,当单击刷新时,该按钮将更新该div的内容。如果不刷新内容,增量将按预期工作,但是刷新后,AngularJS绑定将停止工作。

这在AngularJS中可能无效,但是我最初使用jQuery构建了应用程序,之后又开始使用AngularJS,因此无法将所有内容都迁移到AngularJS。非常感谢在AngularJS中实现此功能的任何帮助。


1
使用JQuery进行此功能是否有任何特殊原因?由于可以轻松地用角度来解决:< jsfiddle.net/pkozlowski_opensource/YCrFD/2 >
pkozlowski.opensource 2012年

3
这只是我实际用例的简化版本,用于显示问题。在实际的应用程序中,grails taglib生成动态内容,并将其作为html传递给jquery。因此,我无法将grails taglib中的所有逻辑移植到angularjs上,以使其变为纯粹的angularjs。
拉惹2012年

1
@ pkozlowski.opensource,该链接已死?你也应该加入outdoor.stackexchange.com :)
Liam

Answers:


115

您需要$compile先将HTML字符串插入HTML,然后再将其插入DOM中,以便angular有机会执行绑定。

在您的小提琴中,它看起来像这样。

$("#dynamicContent").html(
  $compile(
    "<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>"
  )(scope)
);

显然,$compile必须将其注入控制器才能正常工作。

$compile文档中阅读更多内容


2
谢谢Noah,当我在控制器方法中执行编译并将其直接绑定到按钮的click事件时,编译工作正常。这是工作示例。但是我在实际的应用程序中,必须从另一个jquery函数调用controller方法。所以我抓住了对范围对象的引用,并调用了refresh方法来重新编译,这是行不通的。这是例子。您能帮忙这个例子吗?
拉贾(Raja)2012年

1
@Raja在角度框架之外调用角度方法/表达式时,应调用$ scope。$ apply()以执行异常处理,执行监视
Artem Andreev

1
@ArtemAndreev完全正确。@Raja你也可以将呼叫转移到$scope.$apply()进入refresh()功能本身,如果是有意义的,你的架构:jsfiddle.net/nfreitas/8xkeh/1
诺亚塔斯

3
angular-1.0.1.min.js原始示例中的链接是404。这是@ ArtemAndreev-s示例的更新工作版本:jsfiddle.net/pmorch/fABdD/186和@NoahFreitas示例:jsfiddle.net/pmorch/8xkeh/43
Peter

1
在控制器中使用$ compile和操作DOM会导致您走到拥有无法测试的代码的道路。伪指令应该用于更改DOM而不是控制器。
Enzey 2014年

57

万一您无法控制动态内容,另一种解决方案

如果您未通过指令加载元素(例如,在带注释的jsfiddles中的示例中),则此方法有效。

整理您的内容

将内容包装在div中,以便在使用JQuery时可以选择它。您还可以选择使用本机JavaScript来获取元素。

<div class="selector">
    <grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter>
</div>

使用角度喷射器

如果您没有$ compile,则可以使用以下代码获取对$ compile的引用。

$(".selector").each(function () {
    var content = $(this);
    angular.element(document).injector().invoke(function($compile) {
        var scope = angular.element(content).scope();
        $compile(content)(scope);
    });
});

概要

最初的帖子似乎假设您有$ compile参考资料。当您拥有参考文献时,这显然很容易,但是我没有,所以这就是我的答案。

先前代码的一个警告

如果在最小化方案中使用asp.net/mvc捆绑软件,则在以发布模式进行部署时会遇到麻烦。麻烦来自未捕获错误:[$ injector:unpr]的形式,这是由缩小程序与有角度的javascript代码弄乱引起的。

这是补救方法

用以下重载替换之前的代码段。

...
angular.element(document).injector().invoke(
[
    "$compile", function($compile) {
        var scope = angular.element(content).scope();
        $compile(content)(scope);
    }
]);
...

在我拼凑起来之前,这给我带来了很多痛苦。


1
谢谢您,因为上面的代码对我有用,并且提供了有关编译的说明。有时您会错过一些简单的部分:)
Abs 2014年

编译后我不得不消化。
2014年

2
绝对救生员,我在代码中添加了角度条件检查,可让其在插入角度应用程序时使用所有角度优势
LiamRyan 2014年

18

除了@jwize的答案

因为angular.element(document).injector()给出了错误,injector is not defined 所以,我创建了可以在AJAX调用之后或使用jQuery更改DOM时运行的函数。

  function compileAngularElement( elSelector) {

        var elSelector = (typeof elSelector == 'string') ? elSelector : null ;  
            // The new element to be added
        if (elSelector != null ) {
            var $div = $( elSelector );

                // The parent of the new element
                var $target = $("[ng-app]");

              angular.element($target).injector().invoke(['$compile', function ($compile) {
                        var $scope = angular.element($target).scope();
                        $compile($div)($scope);
                        // Finally, refresh the watch expressions in the new element
                        $scope.$apply();
                    }]);
            }

        }

通过仅传递新元素的选择器来使用它。像这样

compileAngularElement( '.user' ) ; 

谢谢,这挽救了我的生命,因为它使用了一个使用UIKit进行对话框的程序包,并在$ scope函数中动态生成了HTML。作为附带说明,我必须更改$ target的选择器以适合我的需要,在我的情况下为$ [“ data-ng-controller]”),并注释掉$ scope.apply();。由于此函数已在角度回调中被调用(因此应用已在进行中)
zontar,

@zontar也可以target通过从参数中获取动态来实现。
shyammakwana.me,2018年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.