現在、アプリケーションにいくつかのbootstrapツールチップを追加しています。
「通常の」ツールチップはすべて問題ありませんが、tooltip-html-unsafe
、空のツールチップだけです。
私のツールチップ:
<a><span tooltip-placement="right" tooltip-html-safe="{{myHTMLText}}"> Help </span></a>
DOMでは、私は持っています:
<div class="tooltip-inner" ng-bind-html-unsafe="content"></div>
Divのコンテンツは空のようなので、ツールチップに表示するものはありません。私はDOMに直接次のようなHTMLテキストを入れようとしました:
<div class="tooltip-inner" ng-bind-html-unsafe="content"><b>test</b></div>
と動作します。
アイデアはありますか?
Html-unsafeディレクティブは、その内容を指すように設計されています。これはどうですか:
<div data-ng-controller="SomeCtrl">
<span data-tooltip-html-unsafe="{{yourContent}}" data-tooltip-placement="right">
Help
</span>
</div>
次に、SomeCtrlで、htmlを保持する変数を作成します。
$scope.yourContent = "<b>my html, yay</b>
bootstrapを変更して要素からコンテンツを取得する場合は、次のように行うことができます。最初に、ツールチップテンプレートを変更して、htmlを取得する関数を呼び出すようにする必要があります。
angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html",
"<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
" <div class=\"tooltip-arrow\"></div>\n" +
" <div class=\"tooltip-inner\" ng-bind-html-unsafe=\"getToolTipHtml()\"></div>\n" +
"</div>\n" +
"");
}]);
次に、tooltipHtmlUnsafePopupのリンク関数を作成します。
.directive( 'tooltipHtmlUnsafePopup', function () {
return {
restrict: 'E',
replace: true,
scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html',
link: function(scope, element, attrs) {
scope.getTooltipHtml = function() {
var elemId = '#' + scope.content;
var htmlContent = $rootElement.find(elemId).html();
return htmlContent;
};
}
};
})
編集:後でui-bootstrapからカスタマイズされたコードを抽出しました。これを使用するためにui-bootstrapを変更する必要がないため、これは良いことです。これが、「bootstrapx」と呼ばれるモジュール内の抽出されたコードです。これはポップオーバー用です(私は実際にはツールチップを使用していなかったため)が、これはツールチップにも簡単に適応できるはずだと感じています。
angular.module("bootstrapx", ["bootstrapx.tpls","bootstrapx.popover","bootstrapx.popover.dismisser"]);
angular.module("bootstrapx.tpls", ["template/popover/popover-html.html","template/popover/popover-html-unsafe.html","template/popover/popover-template.html"]);
angular.module( 'bootstrapx.popover', [ 'ui.bootstrap.tooltip' ] )
.directive('popover', [ function() {
return {
restrict: 'EA',
priority: -1000,
link: function(scope, element) {
element.addClass('popover-link');
}
};
}])
.directive('popoverHtml', [ function() {
return {
restrict: 'EA',
priority: -1000,
link: function(scope, element) {
element.addClass('popover-link');
}
};
}])
.directive('popoverHtmlUnsafe', [ function() {
return {
restrict: 'EA',
priority: -1000,
link: function(scope, element) {
element.addClass('popover-link');
}
};
}])
.directive('popoverTemplate', [ function() {
return {
restrict: 'EA',
priority: -1000,
link: function(scope, element) {
element.addClass('popover-link');
}
};
}])
.directive( 'popoverHtmlPopup', [ function() {
return {
restrict: 'EA',
replace: true,
scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/popover/popover-html.html'
};
}])
.directive( 'popoverHtml', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
return $tooltip( 'popoverHtml', 'popover', 'click' );
}])
.directive( 'popoverHtmlUnsafePopup', [ '$rootElement', function ( $rootElement ) {
return {
restrict: 'EA',
replace: true,
scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/popover/popover-html-unsafe.html',
link: function(scope, element) {
var htmlContent = '';
scope.$watch('content', function(value) {
if (!value) {
return;
}
var elemId = '#' + value;
htmlContent = $rootElement.find(elemId).html();
});
scope.getPopoverHtml = function() {
return htmlContent;
};
}
};
}])
.directive( 'popoverHtmlUnsafe', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
return $tooltip( 'popoverHtmlUnsafe', 'popover', 'click' );
}])
.directive( 'popoverTemplatePopup', [ '$http', '$templateCache', '$compile', '$parse', function ( $http, $templateCache, $compile, $parse) {
return {
restrict: 'EA',
replace: true,
scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
templateUrl: 'template/popover/popover-template.html',
link: function(scope, element, attrs) {
scope.getPopoverTemplate = function() {
var templateName = scope.content + '.html';
return templateName;
};
}
};
}])
.directive( 'popoverTemplate', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
return $tooltip( 'popoverTemplate', 'popover', 'click' );
}]);
angular.module("template/popover/popover-html.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/popover/popover-html.html",
"<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
" <div class=\"arrow\"></div>\n" +
"\n" +
" <div class=\"popover-inner\">\n" +
" <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
" <div class=\"popover-content\" ng-bind-html=\"content\"></div>\n" +
" </div>\n" +
"</div>\n" +
"");
}]);
angular.module("template/popover/popover-html-unsafe.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/popover/popover-html-unsafe.html",
"<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
" <div class=\"arrow\"></div>\n" +
"\n" +
" <div class=\"popover-inner\">\n" +
" <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
" <div class=\"popover-content\" ng-bind-html-unsafe=\"{{getPopoverHtml()}}\"></div>\n" +
" </div>\n" +
"</div>\n" +
"");
}]);
angular.module("template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/popover/popover-template.html",
"<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
" <div class=\"arrow\"></div>\n" +
"\n" +
" <div class=\"popover-inner\">\n" +
" <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
" <div class=\"popover-content\" ng-include=\"getPopoverTemplate()\"></div>\n" +
" </div>\n" +
"</div>\n" +
"");
}]);
angular.module('bootstrapx.popover.dismisser', [])
.directive( 'dismissPopovers', [ '$http', '$templateCache', '$compile', '$parse', function ( $http, $templateCache, $compile, $parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('mouseup', function(e) {
var clickedOutside = true;
$('.popover-link').each(function() {
if ($(this).is(e.target) || $(this).has(e.target).length) {
clickedOutside = false;
return false;
}
});
if ($('.popover').has(e.target).length) {
clickedOutside = false;
}
if (clickedOutside) {
$('.popover').prev().click();
}
});
}
};
}]);
BodyタグにdismissPopoversディレクティブがあります(これはツールチップにも当てはまる可能性が高いので、ニーズに合わせて変更する必要があります)。
<body data-ng-controller="AppController" data-dismiss-popovers>
私は非常に簡単な方法でブートストラップのhtmlツールチップを許可するカスタムディレクティブを作成しました。テンプレートを上書きする必要はありません:
angular.module('vermouthApp.htmlTooltip', [
])
.directive('vaTooltip', ['$http', '$templateCache', '$compile', '$parse', '$timeout', function ($http, $templateCache, $compile, $parse, $timeout)
{
//va-tooltip = path to template or pure tooltip string
//tooltip-updater = scope item to watch for changes when template has to be reloaded [optional (only if template is dynamic)]
//All other attributes can be added for standart boostrap tooltip behavior (ex. tooltip-placement)
return {
restrict: 'A',
scope: true,
compile: function (tElem, tAttrs)
{
//Add bootstrap directive
if (!tElem.attr('tooltip-html-unsafe'))
{
tElem.attr('tooltip-html-unsafe', '{{tooltip}}');
}
return function (scope, element, attrs)
{
scope.tooltip = attrs.vaTooltip;
var tplUrl = $parse(scope.tooltip)(scope);
function loadTemplate()
{
$http.get(tplUrl, { cache: $templateCache }).success(function (tplContent)
{
var container = $('<div/>');
container.html($compile(tplContent.trim())(scope));
$timeout(function ()
{
scope.tooltip = container.html();
});
});
}
//remove our direcive to avoid infinite loop
element.removeAttr('va-tooltip');
//compile element to attach tooltip binding
$compile(element)(scope);
if (angular.isDefined(attrs.tooltipUpdater))
{
scope.$watch(attrs.tooltipUpdater, function ()
{
loadTemplate();
});
} else
{
loadTemplate();
}
};
}
};
}]);
それはあなたがそれをどのように呼ぶか
<a va-tooltip="'tooltipContent.html'" tooltip-updater="item" tooltip-placement="bottom">
<b><i>{{item.properties.length - propertyShowLimit + ' properties more...'}}</i></b>
</a>
そして、テンプレートは次のようにすることができます:
<script id="tooltipContent.html" type="text/ng-template">
<span ng-repeat="prop in item.properties>
<b>{{prop.name}}</b>:
<span ng-repeat="val in prop.values">{{val.value}} </span>
<br />
</span>
</script>
今では組み込みのテンプレート機能があります: https://angular-ui.github.io/bootstrap/#tooltip
<a href="#" uib-tooltip-template="'myTooltipTemplate.html'">Custom template</a>
<script type="text/ng-template" id="myTooltipTemplate.html">
<span>Special Tooltip with <strong>markup</strong> and {{ dynamicTooltipText }}</span>
</script>