AngularJS + JQuery: Angularjs'de çalışan dinamik içerik nasıl elde edilir


84

Hem jQuery hem de AngularJS kullanan bir Ajax uygulaması üzerinde çalışıyorum.

JQuery'nin htmlişlevini kullanarak bir div'in içeriğini (AngularJS bağlamalarını içeren) güncellediğimde , AngularJS bağlamaları çalışmıyor.

Yapmaya çalıştığım şeyin kodu aşağıdadır:

$(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>

Kimliği olan bir div içinde dinamik içeriğim var #dynamicContentve yenile tıklandığında bu div içeriğini güncelleyen bir yenile düğmem var. İçeriği yenilemezsem, artış beklendiği gibi çalışıyor, ancak yeniledikten sonra AngularJS bağlama çalışmayı durduruyor.

Bu, AngularJS'de geçerli olmayabilir, ancak başlangıçta jQuery ile uygulama oluşturdum ve daha sonra AngularJS kullanmaya başladım, bu yüzden her şeyi AngularJS'ye taşıyamıyorum. Bunun AngularJS'de çalışmasıyla ilgili her türlü yardım büyük beğeni topluyor.


1
Bu işlevsellik için JQuery'yi kullanmanın özel bir nedeni var mı? Bu güzel ve kolayca açısal olarak ele alındığı için: < jsfiddle.net/pkozlowski_opensource/YCrFD/2 >
pkozlowski.opensource

3
Bu, sorunu göstermek için gerçek kullanım durumumun sadece basitleştirilmiş bir versiyonudur. Gerçek uygulamada dinamik içerik, html olarak jquery'ye iletilen grails taglib tarafından oluşturulur. Bu yüzden, grails taglib'deki tüm mantığı, onu saf açısal js yapmak için angularjs'ye taşıyamıyorum.
Raja

1
@ pkozlowski.opensource, bu bağlantı öldü mü? Ayrıca katılması gerektiğini outdoors.stackexchange.com :)
Liam

Yanıtlar:


115

Araman gerek $compileAngular'ın bağlamayı gerçekleştirme şansı elde etmesi için DOM'a eklemeden önce HTML dizesini .

Senin kemanında buna benzer bir şey olurdu.

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

Açıkçası, $compilebunun çalışması için kontrol cihazınıza enjekte edilmesi gerekir.

$compileBelgelerde daha fazlasını okuyun .


2
Teşekkürler Noah, derleme, bir denetleyici yönteminde yaptığımda çalışıyor ve bu denetleyici yöntemini düğme olayına tıklamak için doğrudan bağla. İşte çalışma örneği . Ancak gerçek uygulamamda, denetleyici yöntemini farklı bir jquery işlevinden çağırmak zorunda kaldım. bu yüzden kapsam nesnesine referans aldım ve çalışmayan yeniden derlemek için yenileme yöntemini çağırdım. İşte örnek . Bu örneğin işe yaramasına yardımcı olabilir misiniz?
Raja

1
@Raja Açısal çerçevenin dışında açısal yöntemleri / ifadeyi çağırdığınızda , istisna işleme, saatleri yürütme vb. İçin uygun kapsam yaşam döngüsünü gerçekleştirmek için $ kapsamı çağırmalısınız . $ Apply () jsfiddle.net/fABdD/14
Artem Andreev

1
@ArtemAndreev tam olarak doğru. Ayrıca çağrısına hareket olabilir @Raja $scope.$apply()içine refresh(): sizin mimarisi açısından anlamlı olup olmadığını işlevin kendisi jsfiddle.net/nfreitas/8xkeh/1
Nuh Freitas

3
angular-1.0.1.min.jsOrijinal örneklerdeki bağlantı 404'tür. @ ArtemAndreev-s örneğinin güncellenmiş çalışma sürümleri: jsfiddle.net/pmorch/fABdD/186 ve @NoahFreitas örneği: jsfiddle.net/pmorch/8xkeh/43
Peter V. Mørch

1
$ Compile kullanmak ve DOM'u bir denetleyicide kullanmak, sizi test edilemez bir koda sahip olma yolunda yönlendirecektir. Direktifler DOM'u değiştirmek için kullanılmalıdır asla bir kontrolör.
Enzey

57

Dinamik İçerik Üzerinde Kontrolünüz Olmaması Durumunda Başka Bir Çözüm

Bu, öğenizi bir yönerge yoluyla yüklemediyseniz çalışır (yani, yorumlanmış jsfiddles örneğindeki gibi).

İçeriğinizi Toplayın

JQuery kullanıyorsanız içeriğinizi seçebilmeniz için bir div içine sarın . Öğenizi almak için yerel javascript kullanmayı da tercih edersiniz.

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

Açısal Enjektör Kullanın

Eğer yoksa, $ compile başvurusu almak için aşağıdaki kodu kullanabilirsiniz.

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

Özet

Orijinal gönderi, elinizin altında bir $ compile referansınız olduğunu varsayıyor gibiydi. Referansınız olduğunda açıkça kolay, ama ben yapmadım, bu yüzden bu benim için cevaptı.

Önceki kodun bir Uyarısı

Küçültme senaryosuna sahip bir asp.net/mvc paketi kullanıyorsanız, yayın modunda dağıttığınızda başınız belaya girer. Sorun, minifier'ın açısal javascript kodu ile uğraşmasının neden olduğu Yakalanmamış Hata: [$ injector: unpr] şeklinde gelir.

İşte bunu çözmenin yolu :

Önceki kod parçacığını aşağıdaki aşırı yükleme ile değiştirin.

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

Bu, onu bir araya getirmeden önce benim için çok fazla keder yarattı.


1
Yukarıdaki kod benim için çalıştı kapsamı ve derleme hakkında açıklama mevcut olduğu için teşekkürler. bazen kolay kısımları özlüyorsunuz :)
Abs

Derlemeden sonra $ sindirmek zorunda kaldım.
Knu

2
Mutlak cankurtaran,
koduma

18

@ Jwize'nin cevabına ek

Çünkü angular.element(document).injector()hata veriyordu injector is not defined Bu yüzden AJAX çağrısından sonra veya DOM jQuery ile değiştirildiğinde çalıştırabileceğiniz bir fonksiyon yarattım.

  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();
                    }]);
            }

        }

sadece yeni elemanın seçicisini geçerek kullanın. bunun gibi

compileAngularElement( '.user' ) ; 

Teşekkürler, bu, UIKit'i diyalogları için kullanan bir paketle hayatımı kurtardı, HTML $ kapsam işlevi içinde anında oluşturuldu. Bir yan not olarak, $ hedefinin seçicisini ihtiyaçlarıma uyacak şekilde değiştirmem gerekiyordu, benim durumumda $ ["data-ng-controller]") ve $cope.apply (); bu işlev zaten açısal bir geri
aramada

@zontar target, tartışmadan alarak da dinamik hale getirebilirsiniz .
shyammakwana.me
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.