事实证明,使用自定义指令来装饰 ui-bootstrap 工具提示或弹出框并不是很困难。这是用打字稿写的,但它的 javascript 部分应该很明显。这段代码用于装饰工具提示或弹出框:
'use strict';
module App.Directives.TooltipToggle {
export interface DirectiveSettings {
directiveName: string;
directive: any[];
directiveConfig?: any[];
}
export function directiveSettings(tooltipOrPopover = 'tooltip'): DirectiveSettings {
var directiveName = tooltipOrPopover;
// events to handle show & hide of the tooltip or popover
var showEvent = 'show-' + directiveName;
var hideEvent = 'hide-' + directiveName;
// set up custom triggers
var directiveConfig = ['$tooltipProvider', ($tooltipProvider: ng.ui.bootstrap.ITooltipProvider): void => {
var trigger = {};
trigger[showEvent] = hideEvent;
$tooltipProvider.setTriggers(trigger);
}];
var directiveFactory = (): any[] => {
return ['$timeout', ($timeout: ng.ITimeoutService): ng.IDirective => {
var d: ng.IDirective = {
name: directiveName,
restrict: 'A',
link: (scope: ng.IScope, element: JQuery, attr: ng.IAttributes) => {
if (angular.isUndefined(attr[directiveName + 'Toggle'])) return;
// set the trigger to the custom show trigger
attr[directiveName + 'Trigger'] = showEvent;
// redraw the popover when responsive UI moves its source
var redrawPromise: ng.IPromise<void>;
$(window).on('resize', (): void => {
if (redrawPromise) $timeout.cancel(redrawPromise);
redrawPromise = $timeout((): void => {
if (!scope['tt_isOpen']) return;
element.triggerHandler(hideEvent);
element.triggerHandler(showEvent);
}, 100);
});
scope.$watch(attr[directiveName + 'Toggle'], (value: boolean): void => {
if (value && !scope['tt_isOpen']) {
// tooltip provider will call scope.$apply, so need to get out of this digest cycle first
$timeout((): void => {
element.triggerHandler(showEvent);
});
}
else if (!value && scope['tt_isOpen']) {
$timeout((): void => {
element.triggerHandler(hideEvent);
});
}
});
}
};
return d;
}];
};
var directive = directiveFactory();
var directiveSettings: DirectiveSettings = {
directiveName: directiveName,
directive: directive,
directiveConfig: directiveConfig,
};
return directiveSettings;
}
}
使用这段代码,您可以设置工具提示或弹出框的编程隐藏和显示,如下所示:
var tooltipToggle = App.Directives.TooltipToggle.directiveSettings();
var popoverToggle = App.Directives.TooltipToggle.directiveSettings('popover');
var myModule = angular.module('my-mod', ['ui.bootstrap.popover', 'ui.bootstrap.tpls'])
.directive(tooltipToggle.directiveName, tooltipToggle.directive)
.config(tooltipToggle.directiveConfig)
.directive(popoverToggle.directiveName, popoverToggle.directive)
.config(popoverToggle.directiveConfig);
用法:
<span tooltip="This field is required."
tooltip-toggle="formName.fieldName.$error.required"
tooltip-animation="false" tooltip-placement="right"></span>
或者
<span popover="This field is required."
popover-toggle="formName.fieldName.$error.required"
popover-animation="false" popover-placement="right"></span>
因此,我们重用了 ui-bootstrap 工具提示或弹出框附带的所有其他内容,并且只实现了该-toggle
属性。装饰指令监视该属性,并触发自定义事件以显示或隐藏,然后由 ui-bootstrap 工具提示提供程序处理。
更新:
由于此答案似乎对其他人有所帮助,因此这里是编写为 javascript 的代码(上面的打字稿或多或少会编译为此 javascript):
'use strict';
function directiveSettings(tooltipOrPopover) {
if (typeof tooltipOrPopover === "undefined") {
tooltipOrPopover = 'tooltip';
}
var directiveName = tooltipOrPopover;
// events to handle show & hide of the tooltip or popover
var showEvent = 'show-' + directiveName;
var hideEvent = 'hide-' + directiveName;
// set up custom triggers
var directiveConfig = ['$tooltipProvider', function ($tooltipProvider) {
var trigger = {};
trigger[showEvent] = hideEvent;
$tooltipProvider.setTriggers(trigger);
}];
var directiveFactory = function() {
return ['$timeout', function($timeout) {
var d = {
name: directiveName,
restrict: 'A',
link: function(scope, element, attr) {
if (angular.isUndefined(attr[directiveName + 'Toggle']))
return;
// set the trigger to the custom show trigger
attr[directiveName + 'Trigger'] = showEvent;
// redraw the popover when responsive UI moves its source
var redrawPromise;
$(window).on('resize', function() {
if (redrawPromise) $timeout.cancel(redrawPromise);
redrawPromise = $timeout(function() {
if (!scope['tt_isOpen']) return;
element.triggerHandler(hideEvent);
element.triggerHandler(showEvent);
}, 100);
});
scope.$watch(attr[directiveName + 'Toggle'], function(value) {
if (value && !scope['tt_isOpen']) {
// tooltip provider will call scope.$apply, so need to get out of this digest cycle first
$timeout(function() {
element.triggerHandler(showEvent);
});
}
else if (!value && scope['tt_isOpen']) {
$timeout(function() {
element.triggerHandler(hideEvent);
});
}
});
}
};
return d;
}];
};
var directive = directiveFactory();
var directiveSettings = {
directiveName: directiveName,
directive: directive,
directiveConfig: directiveConfig,
};
return directiveSettings;
}