Как заставить ng-bind-html компилировать код angularjs
Я работаю с angularjs 1.2.0-rc.3. Я хотел бы включить HTML-код в шаблон динамически. Для этого я использую в контроллере:
html = "<div>hello</div>";
$scope.unicTabContent = $sce.trustAsHtml(html);
В шаблоне я получил:
<div id="unicTab" ng-bind-html="unicTabContent"></div>
Он отлично работает для обычного HTML-кода. Но когда я пытаюсь поставить угловой шаблон, он не интерпретируется, он просто включается в страницу. Например, я хотел бы включить:
<div ng-controller="formCtrl">
<div ng-repeat="item in content" ng-init="init()">
</div>
</div>
большое спасибо
8 ответов
Это решение не использует жестко закодированные шаблоны, и вы можете компилировать угловые выражения, встроенные в ответ API.
Шаг 1. Установите эту директиву: https://github.com/incuna/angular-bind-html-compile
Шаг 2. Включите директиву в модуль.
angular.module("app", ["angular-bind-html-compile"])
Шаг 3. Используйте директиву в шаблоне:
<div bind-html-compile="letterTemplate.content"></div>
Результат:
Контроллер Объект
$scope.letter = { user: { name: "John"}}
JSON Response
{ "letterTemplate":[
{ content: "<span>Dear {{letter.user.name}},</span>" }
]}
HTML-вывод =
<div bind-html-compile="letterTemplate.content">
<span>Dear John,</span>
</div>
Для справки вот соответствующая директива:
(function () {
'use strict';
var module = angular.module('angular-bind-html-compile', []);
module.directive('bindHtmlCompile', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(function () {
return scope.$eval(attrs.bindHtmlCompile);
}, function (value) {
element.html(value);
$compile(element.contents())(scope);
});
}
};
}]);
}());
Это то, что я сделал, не знаю, угловой ли этоТМ, но он работает и очень прост;
.directive('dynamic', function($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, element, attrs) {
scope.$watch(attrs.dynamic, function(html) {
$compile(element.html(html).contents())(scope);
});
}
};
});
Так;
<div id="unicTab" dynamic="unicTabContent"></div>
Изменить: я нашел угловой путь, и это очень просто.
$templateCache.put('unicTabContent', $sce.trustAsHtml(html));
<div id="unicTab" ng-include="'unicTabContent'"></div>
Не нужно делать свои собственные директивы или что-нибудь. Но эта сделка обязательна, она не увидит изменений, внесенных в ваш html, как это делает пользовательская директива.
Как говорит Винод Луи в своем комментарии, лучший способ сделать это - использовать шаблоны. Мне нужно было определить шаблон за пределами обычного кода, например, я добавил этот код внутри моего index.html:
<script type="text/ng-template" id="unic_tab_template.html">
<div ng-switch on="page">
<div ng-switch-when="home"><p>{{home}}</p></div>
<div ng-switch-when="form">
<div ng-controller="formCtrl">
<div ng-repeat="item in content">{{item.name}}:{{item.value}}</div>
</div>
</div>
<div ng-switch-default>an error accured</div>
</div>
</script>
Этот шаблон является условным, поэтому в зависимости от значения $scope.page он переключается между 3 шаблонами (третий является обработчиком ошибок). Чтобы использовать это у меня было:
<div id="unicTab" ng-controller="unicTabCtrl">
<div ng-include="'unic_tab_template.html'"></div>
</div>
Таким образом, моя страница изменяется в зависимости от области $ внутри моего контроллера unicTabCtrl.
Завершить идею вставки шаблонных швов angularsjs сложно, чтобы реализовать ее ($compile seams - решение, но я не смог заставить его работать). Но вместо этого вы можете использовать условные шаблоны.
Мое решение аналогичной проблемы в моем текущем приложении без использования шаблона (не элегантно, но работает):
directive('ngBindHtmlCompile', ['$compile', function ($compile) {
return {
restrict: 'A',
compile: function compile(tElement, tAttributes, transcludeFn) {
return function postLink(scope, element, attributes) {
scope.$watch(function() {
return scope.$eval(attributes.ngBindHtml);
}, function(newValue, oldValue) {
$compile(element.children())(scope);
});
};
}
};
}]);
Это требует ngBindHtml
на том же элементе и компилирует содержимое элемента после его изменения ngBindHtml
,
<div id="unicTab" ng-bind-html="unicTabContent" ng-bind-html-compile></div>
ng-html-compile
выглядит похоже, но на первый взгляд он не будет пересчитан при изменении содержимого шаблона. Но я не пробовал это.
Я пытался сделать то же самое и наткнулся на этот модуль.
http://ngmodules.org/modules/ng-html-compile
Я просто включил его, и тогда я смог использовать "ng-html-compile" вместо "ng-bind-html"
Одним из способов является использование директивы с целью вставки пользовательских шаблонов, которые включают угловые выражения
<div id="unicTab" unic-tab-content></div>
app.directive("unicTabContent",function(){
return {
restrict:"A",
template:'{{unicTabContent}}'
}
})
Код ниже намного проще, используя встроенные в Angular объекты $interpolate и $sce. Сначала вставьте объекты $interpolate и $sce Angular в вашу директиву, так как вы делаете все, что вам нужно в вашей директиве.
amqApp.directive('myDir', ['$interpolate', '$sce', function ($interpolate,$sce ) {...}
Затем создайте все переменные области, найденные в ваших импортированных выражениях HTML...
$scope.custom = 'Hello World';
Затем используйте $interpolate для обработки вашего пользовательского HTML и его выражений... затем убедитесь, что вы используете объект $sce, чтобы доверять ему как HTML перед привязкой...
var html = $interpolate('<b>{{custom}}</b>')($scope);
$scope.data = $sce.trustAsHtml(html);
Наконец, на ваш взгляд, просто убедитесь, что вы используете элемент с надписью "ng-bind" или "ng-bind-html" на вашем дисплее. Я обнаружил, что кусок $sce не будет отображать HTML как HTML (видит его как текст), если вы не привяжете его в свой HTML-шаблон, как это...
<span ng-bind-html="data"></span>
Вы должны увидеть жирным шрифтом...
Привет, мир
Я использовал этот трюк для импорта в текст /HTML с пользовательскими угловыми {{выражениями}} из web.config.
Очень упрощенное решение @clement-roblot на основе встроенных шаблонов.
контроллер:
app.controller('TestCtrl', [
'$scope',
'$templateCache',
function ($scope, $templateCache) {
$templateCache.put('test.html', '2 + 2 = {{ 2 + 2 }}');
}
]);
Посмотреть:
<div ng-include="'test.html'"></div>