Ситуация
В наше приложение Angular вложена директива с именем Page, поддерживаемая контроллером, которая содержит div с атрибутом ng-bind-html-unsafe. Это назначается переменной $ scope с именем pageContent. Этой переменной назначается динамически генерируемый HTML из базы данных. Когда пользователь переходит на следующую страницу, вызывается БД, и для переменной pageContent устанавливается этот новый HTML, который отображается на экране с помощью ng-bind-html-unsafe. Вот код:
Директива страницы
angular.module('myApp.directives')
.directive('myPage', function ($compile) {
return {
templateUrl: 'page.html',
restrict: 'E',
compile: function compile(element, attrs, transclude) {
// does nothing currently
return {
pre: function preLink(scope, element, attrs, controller) {
// does nothing currently
},
post: function postLink(scope, element, attrs, controller) {
// does nothing currently
}
}
}
};
});
Шаблон директивы страницы ("page.html" из свойства templateUrl выше)
<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>
Контроллер страницы
angular.module('myApp')
.controller('PageCtrl', function ($scope) {
$scope.pageContent = '';
$scope.$on( "receivedPageContent", function(event, args) {
console.log( 'new page content received after DB call' );
$scope.pageContent = args.htmlStrFromDB;
});
});
Это работает. Мы видим, что HTML-код страницы из БД красиво отображается в браузере. Когда пользователь переходит на следующую страницу, мы видим содержимое следующей страницы и так далее. Все идет нормально.
Эта проблема
Проблема здесь в том, что мы хотим иметь интерактивный контент внутри контента страницы. Например, HTML может содержать миниатюру изображения, где, когда пользователь щелкает по нему, Angular должен сделать что-то удивительное, например, отобразить всплывающее модальное окно. Я разместил вызовы методов Angular (ng-click) в строках HTML в нашей базе данных, но, конечно, Angular не будет распознавать ни вызовы методов, ни директивы, если он каким-то образом не анализирует строку HTML, распознает их и компилирует их.
В нашей БД
Контент для страницы 1:
<p>Here's a cool pic of a lion. <img src="lion.png" ng-click="doSomethingAwesone('lion', 'showImage')" > Click on him to see a large image.</p>
Контент для страницы 2:
<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>
Вернувшись в контроллер страницы, мы добавим соответствующую функцию $ scope:
Контроллер страницы
$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}
Я не могу понять, как вызвать этот метод doSomethingAwesome из строки HTML из БД. Я понимаю, что Angular каким-то образом должен анализировать строку HTML, но как? Я читал невнятное бормотание о службе компиляции $, скопировал и вставил несколько примеров, но ничего не работает. Кроме того, в большинстве примеров показано, что динамический контент устанавливается только на этапе связывания директивы. Мы бы хотели, чтобы Пейдж оставался в живых на протяжении всего времени существования приложения. Он постоянно получает, компилирует и отображает новый контент, когда пользователь листает страницы.
В абстрактном смысле, я думаю, вы могли бы сказать, что мы пытаемся динамически вкладывать фрагменты Angular в приложение Angular, и нам нужно иметь возможность менять их местами.
Я несколько раз читал различные фрагменты документации по Angular, а также всевозможные сообщения в блогах и JS возился с человеческим кодом. Я не знаю, полностью ли я неправильно понимаю Angular, или просто упускаю что-то простое, или, может быть, я медленный. В любом случае я мог бы воспользоваться некоторыми советами.
Ответы:
ng-bind-html-unsafe
отображает содержимое только как HTML. Он не привязывает область действия Angular к полученной модели DOM. Для этого нужно использовать$compile
сервис. Я создал этот плункер, чтобы продемонстрировать, как его использовать$compile
для создания директивы рендеринга динамического HTML, введенного пользователями и привязанного к области действия контроллера. Источник размещен ниже.demo.html
script.js
источник
$compile(ele.contents())(scope);
- эта строка решила мою проблему не компилировать угловые компоненты, которые добавляются динамически. Спасибо.В angular 1.2.10 строка
scope.$watch(attrs.dynamic, function(html) {
возвращала ошибку недопустимого символа, потому что она пыталась просмотреть значение, значениеattrs.dynamic
которого было текстом html.Я исправил это, получив атрибут из свойства области
Мой пример
источник
$compile(ele.contents())(scope);
- эта строка решила мою проблему не компилировать угловые компоненты, которые добавляются динамически. Спасибо.Нашел в группе обсуждения Google. Работает для меня.
источник
Ты можешь использовать
директива для динамического связывания html. Однако вам необходимо получить данные через сервис $ sce.
См. Живую демонстрацию на http://plnkr.co/edit/k4s3Bx
источник
var myApp = angular.module('myApp', ['ngSanitize']);
Попробуйте этот код ниже для привязки html через attr
Попробуйте этот element.html (scope.dynamic); чем element.html (attr.dynamic);
источник