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 82

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' ) ;