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