AngularJS: использование $compile на html, который содержит директивы с templateurl

у меня есть устаревшее приложение, которое имеет некоторый контент, вставленный в DOM через jQuery. Я хотел бы, чтобы устаревшие части кодовой базы отвечали за компиляцию html, который она вставляет в DOM.

Я могу заставить его скомпилировать исходный html, используя $compile, но любые элементы DOM, добавленные шаблоном директивы или templateUrl, не компилируются, если я не вызываю $scope.$apply() из самой директивы.

что я здесь делаю не так?

ссылка возиться: http://jsfiddle.net/f3dkp291/15/

2 ответов


как вы, вероятно, поняли, вам нужно позвонить $scope.$apply() для его обновления {{bindings}} из значений области.

но причина, по которой вы не могли сделать это внутри своей асинхронной функции, заключалась в том, что вы компилировали HTML против существующей области для #target, но затем пытается добавить только HTML. Это не сработает, потому что вам нужно иметь скомпилированный узел в DOM, либо путем добавления всего скомпилированного узла с помощью jQuery .append() или аналогичный, или установив DOM innerHTML во-первых, затем компиляция узла, который находится в DOM. После этого вы можете позвонить $apply в этой области и потому, что директива скомпилирована и в DOM, она будет обновлена правильно.

другими словами, измените свой асинхронный код следующим образом.

вместо:

target.innerHTML = $compile(html)($scope)[0].outerHTML
$scope.$apply()

меняем его на:

target.innerHTML = html;
$compile(target)($scope);
$scope.$digest();

обратите внимание, что я сделал $digest() вместо $apply(). Это потому что $apply() дайджест каждой области, начиная от $rootScope. Вам нужно только переварить эту область, с которой вы связаны, поэтому достаточно (и быстрее, для любого приложения разумного размера с большим количеством областей), чтобы просто переварить ее.

раздвоенный скрипка

Update: Angular может компилировать строки и отсоединенные узлы DOM

я только что проверил, и OP был на самом деле прав, предполагая, что Angular может компилировать строки HTML или отдельные узлы DOM просто отлично. Но то, что вам нужно сделать, это убедиться, что вы фактически добавьте скомпилированный узел в DOM, а не только в HTML. Это связано с тем, что Angular хранит такие вещи, как область и информация привязки как данные jQuery/jQueryLite на узле DOM*. Таким образом, вам нужно добавить весь узел с этой дополнительной информацией, чтобы $digest() будет работать.

таким образом, альтернативным способом этой работы является изменение той же части кода OP, что и выше, на:

target.appendChild($compile(html)($scope)[0]);
$scope.$digest()

* Технически он хранится во внутреннем кэше данных jQuery, а ключ кэша хранится на самом узле DOM.


Сначала добавьте элемент к цели, затем скомпилируйте его.

html = angular.element(html);
target = angular.element(target);
target.append(html);
html = $compile(html)($scope)

http://jsfiddle.net/f3dkp291/16/