Pracuję nad aplikacją Ajax, używając zarówno jQuery, jak i AngularJS.
Kiedy aktualizuję zawartość (która zawiera powiązania AngularJS) elementu div przy użyciu html
funkcji jQuery , powiązania AngularJS nie działają.
Poniżej znajduje się kod tego, co próbuję zrobić:
$(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>
Mam dynamiczną zawartość wewnątrz elementu div z identyfikatorem #dynamicContent
i mam przycisk odświeżania, który aktualizowałby zawartość tego elementu div po kliknięciu odświeżania. Przyrost działa zgodnie z oczekiwaniami, jeśli nie odświeżę zawartości, ale po odświeżeniu wiązanie AngularJS przestaje działać.
Może to nie być poprawne w AngularJS, ale początkowo zbudowałem aplikację w jQuery, a później zacząłem używać AngularJS, więc nie mogę przenieść wszystkiego do AngularJS. Każda pomoc w uruchomieniu tego narzędzia w AngularJS jest bardzo mile widziana.
Odpowiedzi:
Musisz wywołać
$compile
łańcuch HTML przed wstawieniem go do DOM, aby angular miał szansę wykonać powiązanie.Na twoich skrzypcach wyglądałoby to mniej więcej tak.
$("#dynamicContent").html( $compile( "<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>" )(scope) );
Oczywiście,
$compile
aby to zadziałało , należy je wstrzyknąć do kontrolera.Przeczytaj więcej w
$compile
dokumentacji .źródło
$scope.$apply()
dorefresh()
samej funkcji, jeśli ma to sens dla Twojej architektury: jsfiddle.net/nfreitas/8xkeh/1angular-1.0.1.min.js
oryginalnych przykładów to 404. Oto zaktualizowane robocze wersje przykładu @ ArtemAndreev-s: jsfiddle.net/pmorch/fABdD/186 i @NoahFreitas przykład: jsfiddle.net/pmorch/8xkeh/43Inne rozwiązanie na wypadek, gdybyś nie miał kontroli nad zawartością dynamiczną
Działa to, jeśli nie załadowałeś swojego elementu przez dyrektywę (np. Jak w przykładzie w skomentowanym jsfiddles).
Podsumuj swoje treści
Zawiń zawartość w element div, aby można go było wybrać, jeśli używasz JQuery . Możesz także zdecydować się na użycie natywnego javascript, aby uzyskać swój element.
<div class="selector"> <grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter> </div>
Użyj wtryskiwacza kątowego
Możesz użyć poniższego kodu, aby uzyskać odwołanie do $ compile, jeśli go nie masz.
$(".selector").each(function () { var content = $(this); angular.element(document).injector().invoke(function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); }); });
Podsumowanie
Oryginalny post wydawał się zakładać, że masz pod ręką odniesienie do $ compile. Jest to oczywiście łatwe, gdy masz odniesienie, ale ja nie, więc to była odpowiedź dla mnie.
Jedno zastrzeżenie poprzedniego kodu
Jeśli używasz pakietu asp.net/mvc ze scenariuszem minify, będziesz mieć kłopoty podczas wdrażania w trybie wydania. Problem pojawia się w postaci błędu Uncaught Error: [$ injector: unpr], który jest spowodowany przez minifier mylący z kątowym kodem javascript.
Oto sposób, aby temu zaradzić :
Zastąp poprzedni fragment kodu następującym przeciążeniem.
... angular.element(document).injector().invoke( [ "$compile", function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); } ]); ...
To wywołało we mnie wiele smutku, zanim złożyłem to w całość.
źródło
Dodatek do odpowiedzi @ jwize
Ponieważ
angular.element(document).injector()
dawał błądinjector is not defined
Tak więc stworzyłem funkcję, którą możesz uruchomić po wywołaniu AJAX lub po zmianie DOM za pomocą jQuery.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(); }]); } }
użyj go, przekazując tylko selektor nowego elementu. lubię to
compileAngularElement( '.user' ) ;
źródło
target
dynamicznym, biorąc go z argumentu.