我有一个连接成角度的表单,使用它进行验证。我可以使用ng-show指令显示错误消息,如:
<span ng-show="t3.f.needsAttention(f.fieldName)" ng-cloak>
<span ng-show="f.fieldName.$error.required && !f.fieldName.$viewValue">
This field is required.
</span>
</span>
..其中f
是表单,t3
来自表单上的自定义指令,用于检测是否尝试提交,并包含用于检查字段有效性的函数。
我想要完成的是在popover中显示验证消息。无论是bootstrap的原生popover,还是来自UI Bootstrap的popover,我都加载了。我也可以考虑AngularStrap,如果使用那个lib更容易。
我现在正在努力的是一般的弹出窗口的性质 - 它们基于点击,鼠标中心,模糊等用户事件进行自动显示。我想做的是show&amp;根据上面ng-show属性中的相同功能隐藏弹出窗口。因此当表达式返回false时隐藏它,当它返回true时,显示它。
我知道bootstrap有.popover('show'),但是我不应该告诉角度有关dom的任何内容,所以我不确定如何访问$(element).popover ()如果在自定义表单控制器功能中执行此操作。我错过了什么吗?
更新
重复投票中提到的解决方案仍然只显示mouseenter上的popover。我想强制它显示,好像在做$('#popover_id').popover('show')
。
答案 0 :(得分:29)
您还可以构建自己的扩展触发器。这将适用于Tooltip和Popover。
首先按如下方式扩展Tooltip触发器:
// define additional triggers on Tooltip and Popover
app.config(['$tooltipProvider', function($tooltipProvider){
$tooltipProvider.setTriggers({
'show': 'hide'
});
}]);
然后在HTML标记上定义触发器,如下所示:
<div id="RegisterHelp" popover-trigger="show" popover-placement="left" popover="{{ 'Login or register here'}}">
现在你可以通过JavaScript调用hide和show,这是一个3秒内的节目。
$("#RegisterHelp").trigger('show');
//Close the info again
$timeout(function () {
$("#RegisterHelp").trigger('hide');
}, 3000);
答案 1 :(得分:20)
事实证明,用自定义指令装饰ui-bootstrap工具提示或popover并不是很困难。这是用typescript编写的,但它的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;
}
答案 2 :(得分:16)
ui.bootstrap
0.13.4和更新:引入了一个新参数(popover-is-open
)来控制官方ui.bootstrap
回购中的弹出窗口。这是您在最新版本中使用它的方式:
<a uib-popover="Hello world!" popover-is-open="isOpen" ng-click="isOpen = !isOpen">
Click me to show the popover!
</a>
ui.bootstrap
0.13.3及更早版本:我刚刚发布了一个小指令,可以在GitHub上添加对弹出窗口的更多控制权:
https://github.com/Elijen/angular-popover-toggle
您可以使用范围变量来显示/隐藏使用popover-toggle="variable"
指令的弹出窗口,如下所示:
<span popover="Hello world!" popover-toggle="isOpen">
Popover here
</span>
这是一个演示Plunkr:
http://plnkr.co/edit/QeQqqEJAu1dCuDtSvomD?p=preview
答案 3 :(得分:4)
我的方法:
想法是将DOM操作留给指令。
我已经把一个小提琴放在一起,我希望能给出一个更好的解释,但是你会在你提到的UI Bootstrap中找到更复杂的解决方案。
标记:
<div ng-repeat="element in elements" class="element">
<!-- Only want to show a popup if the element has an error and is being hovered -->
<div class="popover" ng-show="element.hovered && element.error" ng-style>Popover</div>
<div class="popoverable" ng-mouseEnter="popoverShow(element)" ng-mouseLeave="popoverHide(element)">
{{ element.name }}
</div>
</div>
JS:
function DemoCtrl($scope)
{
$scope.elements = [
{name: 'Element1 (Error)', error: true, hovered: false},
{name: 'Element2 (no error)', error: false, hovered: false},
{name: 'Element3 (Error)', error: true, hovered: false},
{name: 'Element4 (no error)', error: false, hovered: false},
{name: 'Element5 (Error)', error: true, hovered: false},
];
$scope.popoverShow = function(element)
{
element.hovered = true;
}
$scope.popoverHide = function(element)
{
element.hovered = false
}
}
答案 4 :(得分:4)
对于其他人来说,从0.13.4版本开始,我们已经添加了通过Angular UI Bootstrap库中工具提示和弹出窗口上的*-is-open
属性以编程方式打开和关闭弹出窗口的功能。因此,没有任何理由必须推出自己的代码/解决方案。
答案 5 :(得分:3)
来自Michael Stramel的回答,但是有一个完整的angularJS解决方案:
// define additional triggers on Tooltip and Popover
app.config(['$tooltipProvider', function($tooltipProvider){
$tooltipProvider.setTriggers({
'show': 'hide'
});
}])
现在添加此指令:
app.directive('ntTriggerIf', ['$timeout',
function ($timeout) {
/*
Intended use:
<div nt-trigger-if={ 'triggerName':{{someCodition === SomeValue}},'anotherTriggerName':{{someOtherCodition === someOtherValue}} } ></div>
*/
return {
restrict: 'A',
link: function (scope, element, attrs) {
attrs.$observe('ntTriggerIf', function (val) {
try {
var ob_options = JSON.parse(attrs.ntTriggerIf.split("'").join('"') || "");
}
catch (e) {
return
}
$timeout(function () {
for (var st_name in ob_options) {
var condition = ob_options[st_name];
if (condition) {
element.trigger(st_name);
}
}
})
})
}
}
}])
然后在你的标记中:
<span tooltip-trigger="show" tooltip="Login or register here" nt-trigger-if="{'show':{{ (errorConidtion) }}, 'hide':{{ !(errorConidtion) }} }"></span>