Je travaille sur une application Ajax utilisant à la fois jQuery et AngularJS.
Lorsque je mets à jour le contenu (qui contient des liaisons AngularJS) d'un div à l'aide de la html
fonction de jQuery , les liaisons AngularJS ne fonctionnent pas.
Voici le code de ce que j'essaye de faire:
$(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>
J'ai du contenu dynamique à l'intérieur d'un div avec l'ID #dynamicContent
, et j'ai un bouton d'actualisation qui mettrait à jour le contenu de ce div lorsque l'actualisation est cliquée. L'incrément fonctionne comme prévu si je n'actualise pas le contenu, mais après l'actualisation, la liaison AngularJS cesse de fonctionner.
Cela n'est peut-être pas valide dans AngularJS, mais j'ai initialement créé une application avec jQuery et j'ai commencé à utiliser AngularJS plus tard, donc je ne peux pas tout migrer vers AngularJS. Toute aide pour faire fonctionner cela dans AngularJS est grandement appréciée.
Réponses:
Vous devez appeler
$compile
la chaîne HTML avant de l'insérer dans le DOM afin que angular ait une chance d'effectuer la liaison.Dans votre violon, cela ressemblerait à quelque chose comme ça.
$("#dynamicContent").html( $compile( "<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>" )(scope) );
De toute évidence,
$compile
doit être injecté dans votre contrôleur pour que cela fonctionne.En savoir plus dans la
$compile
documentation .la source
$scope.$apply()
larefresh()
fonction elle-même si cela a du sens pour votre architecture: jsfiddle.net/nfreitas/8xkeh/1angular-1.0.1.min.js
dans les exemples originaux était 404. Voici les versions de travail mises à jour de l'exemple @ ArtemAndreev-s: jsfiddle.net/pmorch/fABdD/186 et @NoahFreitas exemple: jsfiddle.net/pmorch/8xkeh/43Une autre solution au cas où vous ne contrôlez pas le contenu dynamique
Cela fonctionne si vous n'avez pas chargé votre élément via une directive (c'est-à-dire comme dans l'exemple des jsfiddles commentés).
Récapitulez votre contenu
Enveloppez votre contenu dans un div afin de pouvoir le sélectionner si vous utilisez JQuery . Vous pouvez également choisir d'utiliser du javascript natif pour obtenir votre élément.
<div class="selector"> <grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter> </div>
Utiliser l'injecteur angulaire
Vous pouvez utiliser le code suivant pour obtenir une référence à $ compile si vous n'en avez pas.
$(".selector").each(function () { var content = $(this); angular.element(document).injector().invoke(function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); }); });
Sommaire
Le message original semblait supposer que vous aviez une référence $ compile à portée de main. C'est évidemment facile lorsque vous avez la référence, mais je ne l'ai pas fait, donc c'était la réponse pour moi.
Une mise en garde du code précédent
Si vous utilisez un bundle asp.net/mvc avec un scénario minify, vous aurez des problèmes lorsque vous déployez en mode version. Le problème se présente sous la forme d'une erreur non interceptée: [$ injector: un] qui est causée par le minificateur jouant avec le code javascript angulaire.
Voici comment y remédier :
Remplacez l'extrait de code précédent par la surcharge suivante.
... angular.element(document).injector().invoke( [ "$compile", function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); } ]); ...
Cela m'a causé beaucoup de chagrin avant de le reconstituer.
la source
Ajout à la réponse de @ jwize
Parce que
angular.element(document).injector()
donnait une erreurinjector is not defined
Donc, j'ai créé une fonction que vous pouvez exécuter après un appel AJAX ou lorsque DOM est modifié à l'aide de 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(); }]); } }
utilisez-le en passant juste le sélecteur de nouvel élément. comme ça
compileAngularElement( '.user' ) ;
la source
target
dynamique en le prenant à partir d'un argument.