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>
Ответы
Ответ 1
Вам нужно вызвать $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
документации.
Ответ 2
Другое решение в случае, если у вас нет контроля над динамическим контентом
Это работает, если вы не загрузили свой элемент через директиву (то есть, как в примере в комментариях jsfiddles).
Оберните свой контент
Оберните свой контент в div, чтобы его можно было выбрать, если вы используете JQuery. Вы также можете использовать собственный javascript для получения вашего элемента.
<div class="selector">
<grid-filter columnname="LastNameFirstName" gridname="HomeGrid"></grid-filter>
</div>
Использовать Angular Инжектор
Вы можете использовать следующий код, чтобы получить ссылку на компиляцию $, если у вас ее нет.
$(".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 с минимальным сценарием, у вас появятся проблемы при развертывании в режиме выпуска. Проблема возникает в виде ошибки Uncaught: [$ injector: unpr], которая вызвана беспорядком minifier с кодом javascript Angular.
Вот способ его устранения:
Замените предыдущий фрагмент кода следующей перегрузкой.
...
angular.element(document).injector().invoke(
[
"$compile", function($compile) {
var scope = angular.element(content).scope();
$compile(content)(scope);
}
]);
...
Это вызвало много горя для меня, прежде чем я собрал его вместе.
Ответ 3
Дополнение к ответу @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' ) ;