例如,我有要显示表单输入错误的表单。
如果有一些错误,我需要在输入标签附近显示红色徽章(带有“悬停显示错误”)。如果用户将鼠标悬停在红色徽章上,他将使用AngularJS UI Bootstrap工具提示查看错误列表。我不想将错误列表放到tooltip-html-unsafe属性中,因为它不方便编辑和维护。
此代码更具声明性:
<validation-tooltip ng-show="appForm.number.$invalid && appForm.number.$dirty"> <ul> <li ng-show="appForm.number.$error.required">this field is required</li> <li ng-show="appForm.number.$error.number">should be number</li> <li ng-show="appForm.number.$error.min">minimum - 5</li> <li ng-show="appForm.number.$error.max">miximum - 20</li> </ul> </validation-tooltip>
比这段代码:
<span tooltip-html-unsafe="{{<ul><li>This field is required;</li><li>...</li></ul>}}">hover to show errors</span>
如何使用AngularJS UI Bootstrap工具提示编写这样的validate-tooltip指令?
或者,您是否可以建议其他方法来维护验证错误消息?
演示小提琴
validateTooltip是主要指令。它具有以下职责:
通过其包含的内容定义工具提示模板 跟踪验证表达式,以便可以在每个摘要循环中对其进行评估。 公开用于允许valiationMessage指令自行注册的控制器API 在指令上提供“目标”属性,以指定徽章(和相关的工具提示)将绑定到的表单字段
补充笔记
工具提示模板使用链接函数中的包含函数将模板绑定到指令的作用域。模板可以绑定到范围内的两个属性:
$ form :绑定到父范围中定义的表单模型。即$ scope.myForm $ field :绑定到父作用域中的form.name模型。即$ scope.myForm.myInput
这允许模板绑定到验证属性,例如$ valid,$ invalid,$ pristine,$ dirty和$ error,而无需直接引用表单名称或输入字段的名称。例如,以下所有表达式都是有效的绑定表达式:
$ form属性:
$ field属性:
$ field。$ pristine
指令实施
app.directive('validationTooltip', function ($timeout) { return { restrict: 'E', transclude: true, require: '^form', scope: {}, template: '<span class="label label-danger span1" ng-show="errorCount > 0">hover to show err</span>', controller: 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; }); }, link: function (scope, element, attr, formController, transcludeFn) { scope.$form = formController; transcludeFn(scope, function (clone) { var badge = element.find('.label'); var tooltip = angular.element('<div class="validationMessageTemplate tooltip-danger" />'); tooltip.append(clone); element.append(tooltip); $timeout(function () { scope.$field = formController[attr.target]; badge.tooltip({ placement: 'right', html: true, title: clone }); }); }); } } });
validateMessage指令跟踪要在工具提示中显示的验证消息。它用于ng-if定义要求值的表达式。如果ng- if在元素上没有找到,则表达式将简单地计算为true(始终显示)。
ng-if
ng- if
app.directive('validationMessage', function () { return { restrict: 'A', priority: 1000, require: '^validationTooltip', link: function (scope, element, attr, ctrl) { ctrl.$addExpression(attr.ngIf || true ); } } });
添加具有名称属性的表单 添加一个或多个表单域-每个表单域都有一个name属性和一个ng-model指令。 声明<validation-tooltip>具有target属性的元素,该属性引用表单字段之一的名称。 使用validation-message可选的ng-if绑定表达式将指令应用于每个消息。
<validation-tooltip>
target
validation-message
<div ng-class="{'form-group': true, 'has-error':form.number.$invalid}"> <div class="row"> <div class="col-md-4"> <label for="number">Number</label> <validation-tooltip target="number"> <ul class="list-unstyled"> <li validation-message ng-if="$field.$error.required">this field is required </li> <li validation-message ng-if="$field.$error.number">should be number</li> <li validation-message ng-if="$field.$error.min">minimum - 5</li> <li validation-message ng-if="$field.$error.max">miximum - 20</li> </ul> </validation-tooltip> </div> </div> <div class="row"> <div class="col-md-4"> <input type="number" min="5" max="20" ng-model="number" name="number" class="form-control" required /> </div> </div> </div>