Как сообщить AngularJS, что я обманывал его с помощью jQuery?

Я взламываю интерфейс администратора, используя шаблон pre-fab. Уже построенная система навигации использует jQuery для загрузки содержимого в тег через AJAX на основе window.location.hash.

Если я извлечу это, отрезанный через вызов AJAX, а затем вставьте его в DOM:

<div ng-app="myApp">
 {{ 2 + 2 }}
</div>

AngularJS не знает, что я обновил DOM. Содержание, которое я вижу, буквально {{ 2 + 2 }}. Если я перезагружу страницу, выражение оценивается, и я вижу желаемое значение 4.

Как я могу попросить AngularJS оценить контент, который я так жестоко принудил к DOM с помощью неангулярных методов?

Здесь сценарий: http://jsfiddle.net/4zRTH/

ИЗМЕНИТЬ

Ответ от @tasseKATT отлично подходит для простых выражений, но у меня возникают проблемы с доступом к контроллеру. У меня есть NotesController, который должен получить доступ к коду, который я импортирую. Что-то еще по строкам:

<div ng-controller="NotesController">
 {{ notes.length }}
</div>

Я обновил скрипку, чтобы она немного больше соответствовала тому, что я хочу сделать: http://jsfiddle.net/5Xhs9/4/

3 ответа

Вам нужно использовать $apply:

$apply() используется для выполнения выражения в angular извне angular. (Например, из событий браузера DOM, setTimeout, XHR или сторонние библиотеки). Потому что мы призываем структура angular, нам необходимо выполнить правильный жизненный цикл обработка исключений, выполнение часов.

В вашем примере, однако, приложение даже не загружено, поэтому вам нужно:

1) Выберите элемент:

var dynamicContent = "<div id="someId" ng-app=""> {{ 2 + 2 }} </div>";
$('.expression').html(dynamicContent);
var element = angular.element(document.querySelector('#someId'));

2) Загрузите его:

angular.bootstrap(element, []);

3) Измените область действия:

var elementScope = element.scope();

4) Применить $apply:

elementScope.$apply();

Демо: http://jsfiddle.net/5Xhs9/

Изменить для нового сценария:

В вашем новом примере вы добавили ng-app"myApp" в существующий div, поэтому AngularJS загрузит ваше приложение для вас, и теперь вы хотите динамически добавлять это содержимое вместо этого:

<div id="notes" ng-controller="NotesController"> {{ notes.length }} </div>

Вы уже определили NotesController и добавили его в модуль. Теперь вы можете сделать следующее:

1) Извлеките сервис $injector:

var $injector = angular.element(document.querySelector('.container')).injector();

2) Используйте $injector, чтобы скомпилировать недавно добавленный элемент и связать его со своим scope. Вызовите $apply:

var element = angular.element(document.querySelector('#notes'));
$injector.invoke(function($compile) {
 var scope = element.scope();
 $compile(element)(scope);
 scope.$apply();
});

Демо: http://plnkr.co/edit/P6VwLee6AUWO7aDT601m?p=preview


Вы можете обмануть, сохранив $compile и $rootScope в функции app.run на window: http://plnkr.co/edit/pxGhof1zD0rZknagfmyc?p=preview

window.compileForAngular = null;
window.rootScope = null;
var app = angular.module('jQuery', []);
app.run(function ($compile, $rootScope) {
 window.rootScope = $rootScope;
 window.compileForAngular = $compile;
 doNotTryThisAtHome();
});
function doNotTryThisAtHome() {
 // let just pretend that this came in over an AJAX request
var dynamicContent = "<div> {{ 2 + 2 }} </div>";
// I insert it into the DOM via jQuery
$('.expression').html(window.compileForAngular(dynamicContent)(window.rootScope));
}


http://jsfiddle.net/QC97L/2/

См. приведенный выше скрипт

// Code goes here
jQuery(document).ready(function () {
// let just pretend that this came in over an AJAX request
var dynamicContent = "<div id="mainApp"> {{ 2 + 2 }} </div>";
// I insert it into the DOM via jQuery
$('.expression').html(dynamicContent);
 var app = angular.module('myApp',[])
 angular.bootstrap('#mainApp',['myApp']);
// now how do I get AngularJS to evalulate the expression?
});

licensed under cc by-sa 3.0 with attribution.