2012-08-02 65 views
81

我正在使用jQuery和AngularJS处理Ajax应用程序。AngularJS + JQuery:如何获取在angularjs中工作的动态内容

当我使用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 #dynamicContent一个div里面的动态内容,和我有一个刷新按钮,将更新内容点击刷新时该div的值。如果我不刷新内容,Increment按预期工作,但在刷新后,AngularJS绑定停止工作。

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

+1

在这个 功能中使用JQuery有什么特别的理由吗?由于这很好,很容易被角度覆盖: 2012-08-02 05:48:32

+3

这只是我的真实用例的简化版本来显示问题。在实际应用程序中,动态内容是由grails taglib生成的,它以html的形式传递给jquery。所以我无法将grails taglib中的所有逻辑都移植到angularjs中,以使其成为纯粹的angularjs。 – Raja 2012-08-02 14:57:50

+1

@ pkozlowski.opensource,那个链接已经死了?你也应该加入http://outdoors.stackexchange.com/ :) – Liam 2014-02-14 11:09:53

回答

113

您需要先在HTML字符串上调用$compile,然后再将其插入到DOM中,这样角才有机会执行绑定。

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

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

显然,$compile必须注射到控制器中这个工作。

了解更多$compile documentation

+2

感谢诺亚,当我在控制器方法中完成编译工作并直接绑定该控制器方法来单击按钮事件。这里是工作[示例](http://jsfiddle.net/fABdD/10/)。但我在我的实际应用程序中,我不得不从另一个jquery函数调用控制器方法。所以我抓住引用范围对象,并调用刷新方法重新编译这是行不通的。这里是[示例](http://jsfiddle.net/fABdD/12/)。你能帮助我们学习这个例子吗? – Raja 2012-08-02 20:13:47

+1

@Raja当您在角度框架之外调用角度方法/表达式时,应该调用[$ scope。$ apply()](http://docs.angularjs.org/api/ng.$ro​​otScope.Scope)来执行适当的范围生命周期的异常处理,执行手表等。 http://jsfiddle.net/fABdD/14/ – 2012-08-03 04:59:44

+1

@ArtemAndreev完全正确。 @Raja如果你的架构有意义,你也可以将调用移动到'refresh()'函数本身:'$ scope。$ apply()':http://jsfiddle.net/nfreitas/8xkeh/1/ – 2012-08-03 15:21:43

54

另一种解决方案的情况下,你就不用管了对动态内容

这工作,如果你没有通过指令(即像在评论jsfiddles的例子)加载你的元素。

总结了自己的内容

包裹在一个div您的内容,这样就可以,如果你使用的是JQuery的选择它。你也可以选择使用原生javascript来获取你的元素。

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

使用角度喷油器

您可以使用下面的代码来得到,如果你没有一个$参考编译。

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

摘要

原来的职位似乎假设你有一个$编译参考得心应手。当你有参考资料时,显然很容易,但我没有,所以这是我的答案。前面的代码

一个警告如果您使用的是带有缩小场景中asp.net/mvc包,你会遇到麻烦,当你在释放模式部署。麻烦来自Uncaught Error的形式:[$ injector:unpr]这是由缩小器与角度javascript代码搞乱造成的。

这里是弥补它方式:

更换prevous代码段有以下过载。

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

在我拼凑起来之前,这给我造成了很多的伤痛。

+1

感谢上面的代码为我工作的范围和关于编译可用的解释。有时你错过了简单的部分:) – Abs 2014-08-12 11:52:25

+0

编译后我不得不$消化。 – Knu 2014-09-12 13:14:29

+2

绝对救生员,我在我的代码中添加了一个有条件的角度检查,允许它在插入角度应用程序时使用所有角度优点 – SMC 2014-12-03 10:43:43

15

加成@ jwize的回答

因为angular.element(document).injector()是给错误injector is not defined 所以,我创建的功能,可以在DOM使用jQuery改变AJAX调用后运行或。

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') ; 
+0

“[ng-app]”帮助了我,谢谢 – tylerlindell 2016-12-09 23:01:24

+0

谢谢,这使我的生活一个使用UIKit作为其对话框的程序包,在$ scope函数中动态生成HTML。作为一个方面说明,我不得不改变$ target的选择符以满足我的需求,在我的情况下为$ [“data-ng-controller]”),并注释掉$ scope.apply();因为这个函数已经在一个角度回调中被调用(所以应用已经在发生) – zontar 2017-05-06 09:25:00