2012-08-02 64 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