Estoy trabajando en una aplicación Ajax usando jQuery y AngularJS.
Cuando actualizo el contenido (que contiene enlaces AngularJS) de un div usando la html
función de jQuery , los enlaces AngularJS no funcionan.
A continuación se muestra el código de lo que estoy tratando de hacer:
$(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>
Tengo contenido dinámico dentro de un div con la ID #dynamicContent
, y tengo un botón de actualización que actualizaría el contenido de este div cuando se hace clic en actualizar. Increment funciona como se esperaba si no actualizo el contenido, pero después de actualizar, el enlace AngularJS deja de funcionar.
Es posible que esto no sea válido en AngularJS, pero inicialmente creé la aplicación con jQuery y comencé a usar AngularJS más adelante, así que no puedo migrar todo a AngularJS. Cualquier ayuda para que esto funcione en AngularJS es muy apreciada.
Respuestas:
Debe llamar
$compile
a la cadena HTML antes de insertarla en el DOM para que angular tenga la oportunidad de realizar el enlace.En tu violín, se vería así.
$("#dynamicContent").html( $compile( "<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>" )(scope) );
Obviamente,
$compile
debe inyectarse en su controlador para que esto funcione.Leer más en la
$compile
documentación .fuente
$scope.$apply()
larefresh()
función en sí si tiene sentido para su arquitectura: jsfiddle.net/nfreitas/8xkeh/1angular-1.0.1.min.js
en los ejemplos originales era 404. Aquí hay versiones de trabajo actualizadas del ejemplo de @ ArtemAndreev-s: jsfiddle.net/pmorch/fABdD/186 y ejemplo de @NoahFreitasOtra solución en caso de que no tenga control sobre el contenido dinámico
Esto funciona si no cargó su elemento a través de una directiva (es decir, como en el ejemplo de los jsfiddles comentados).
Resuma su contenido
Envuelva su contenido en un div para que pueda seleccionarlo si está usando JQuery . También puede optar por utilizar javascript nativo para obtener su elemento.
<div class="selector"> <grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter> </div>
Usar inyector angular
Puede usar el siguiente código para obtener una referencia a $ compile si no tiene una.
$(".selector").each(function () { var content = $(this); angular.element(document).injector().invoke(function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); }); });
Resumen
La publicación original parecía asumir que tenías una referencia de compilación de $ a la mano. Obviamente, es fácil cuando tienes la referencia, pero yo no, así que esta fue la respuesta para mí.
Una advertencia del código anterior
Si está utilizando un paquete asp.net/mvc con escenario minify, tendrá problemas cuando implemente en modo de lanzamiento. El problema viene en forma de Error no detectado: [$ injector: unpr] que es causado por el minificador jugando con el código javascript angular.
Esta es la forma de remediarlo :
Reemplace el fragmento de código anterior con la siguiente sobrecarga.
... angular.element(document).injector().invoke( [ "$compile", function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); } ]); ...
Esto me causó mucho dolor antes de reconstruirlo.
fuente
Adición a la respuesta de @ jwize
Porque
angular.element(document).injector()
estaba dando un errorinjector is not defined
Entonces, he creado una función que puede ejecutar después de la llamada AJAX o cuando se cambia DOM usando 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(); }]); } }
utilícelo pasando solo el selector de nuevo elemento. Me gusta esto
compileAngularElement( '.user' ) ;
fuente
target
dinámico tomándolo del argumento.