For example I have the form where I am showing form input errors.
I need to show red badge (with \'hover to show errors\') near input label if there are some errors.
Great answer from @pixelbits. I used his directives and modified them slightly to allow the tooltip to display over the actual input as some users requested.
angular.module('app')
.directive('validationTooltip', ['$timeout', function ($timeout) {
function toggleTooltip(scope) {
if (!scope.tooltipInstance) {
return;
}
$timeout(function() {
if (scope.errorCount > 0 && (scope.showWhen == undefined || scope.showWhen())) {
scope.tooltipInstance.enable();
scope.tooltipInstance.show();
} else {
scope.tooltipInstance.disable();
scope.tooltipInstance.hide();
}
});
}
return {
restrict: 'E',
transclude: true,
require: '^form',
scope: {
showWhen: '&',
placement: '@',
},
template: '',
controller: ['$scope', function ($scope) {
var expressions = [];
$scope.errorCount = 0;
this.$addExpression = function (expr) {
expressions.push(expr);
}
$scope.$watch(function () {
var count = 0;
angular.forEach(expressions, function (expr) {
if ($scope.$eval(expr)) {
++count;
}
});
return count;
}, function (newVal) {
$scope.errorCount = newVal;
toggleTooltip($scope);
});
}],
link: function (scope, element, attr, formController, transcludeFn) {
scope.$form = formController;
transcludeFn(scope, function (clone) {
var tooltip = angular.element('');
tooltip.append(clone);
element.append(tooltip);
$timeout(function () {
scope.$field = formController[attr.target];
var targetElm = $('[name=' + attr.target + ']');
targetElm.tooltip({
placement: scope.placement != null ? scope.placement : 'bottom',
html: true,
title: clone,
});
scope.tooltipInstance = targetElm.data('bs.tooltip');
toggleTooltip(scope);
if (scope.showWhen) {
scope.$watch(scope.showWhen, function () {
toggleTooltip(scope);
});
}
});
});
}
}
}]);
The major change is that the directive uses jQuery to find the target element (which should be an input) via the name attribute, and initializes the tooltip on that element rather than the element of the directive. I also added a showWhen property to the scope as you may not always want your tooltip to show when the input is invalid (see example below).
The validationMessage directive is unchanged
angular.module('app').directive('validationMessage', function () {
return {
restrict: 'A',
priority: 1000,
require: '^validationTooltip',
link: function (scope, element, attr, ctrl) {
ctrl.$addExpression(attr.ngIf || true);
}
}
});
Usage in Html is also similar, with just the addition of showWhen if you want:
- Note required