AngularJS + JQuery: как получить динамический контент, работающий в angularjs
Я работаю над приложением Ajax, используя как jQuery, так и AngularJS.
когда я обновляю содержимое (которое содержит привязки AngularJS) div с помощью jQuery html
функция, привязки 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>
у меня есть динамический контент внутри div с идентификатором #dynamicContent
, и у меня есть кнопка обновления, которая обновит содержимое этого div, когда щелкните обновить. Инкремент работает так, как ожидалось, если я не обновляю содержимое, но после обновления привязка AngularJS перестает работать.
Это может быть недопустимо в AngularJS, но я изначально построил приложение с jQuery и начал использовать AngularJS позже, поэтому я не могу перенести все в AngularJS. Любая помощь в получении этой работы в AngularJS очень ценится.
3 ответа:
нужно позвонить
$compile
в строке HTML перед вставкой ее в DOM, чтобы angular получил возможность выполнить привязку.В вашей скрипке это будет выглядеть примерно так.
$("#dynamicContent").html( $compile( "<button ng-click='count = count + 1' ng-init='count=0'>Increment</button><span>count: {{count}} </span>" )(scope) );
очевидно,
$compile
должен быть введен в контроллер для этого, чтобы работать.подробнее на
$compile
документация.
другое решение в случае, если у вас нет контроля над динамическим контентом
это работает, если вы не загрузили свой элемент через директиву (т. е. как и в Примере в комментариях jsfiddles).
оберните свой контент
оберните содержимое в div, чтобы вы могли выбрать его, если вы используете JQuery. Вы также можете использовать собственный javascript, чтобы получить свой элемент.
<div class="selector"> <grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter> </div>
использовать Угловой Инжектор
вы можете использовать следующий код, чтобы получить ссылку на $compile, если у вас ее нет.
$(".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 связка с minify случае вы получите проблемы при развертывании в режиме релиза. Проблема возникает в виде неперехваченной ошибки: [$injector: unpr], которая вызвана тем, что минификатор возится с угловым кодом javascript.
вот как это исправить:
замените предыдущий фрагмент кода следующей перегрузкой.
... angular.element(document).injector().invoke( [ "$compile", function($compile) { var scope = angular.element(content).scope(); $compile(content)(scope); } ]); ...
Это вызвало много горя для меня, прежде чем я собрал его вместе.
дополнение к ответу @jwize
, потому что
angular.element(document).injector()
дает ошибкуinjector is not defined
Итак, я создал функцию, которую вы можете запустить после вызова AJAX или при изменении DOM с помощью 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(); }]); } }
используйте его, передавая только селектор нового элемента. вот так
compileAngularElement( '.user' ) ;