如何使用bootstrap和angularJS基于同一表单中的另一个字段验证字段?

时间:2014-08-08 08:50:41

标签: angularjs twitter-bootstrap

我有一张表格。为了验证字段(在客户端),我使用了一些HTML5和ng-message来显示错误。

其中两个字段的行为与其他字段不同。

如果填写了这两个字段中的一个,则另一个字段也应填写。

另一方面,如果两者都没有填写,表格应该接受这两个字段为有效。

我希望在表单中有直接反馈,只要用户在两个字段之一中输入内容,另一个应该显示相应的消息。

以下代码中的2个字段为fWebsiteURLfWebsiteName

在我的指令/表单中实现这种逻辑的最佳方法是什么?

这是我部分的部分(使用jade和bootstrap 2.x.x)。

目前,只为每个字段进行了基本的required验证,使其成为所有表单的必填项。

感谢您的帮助。

    form.form-horizontal(name="scheduleForm")
    .control-group(ng-class="{error: scheduleForm.fProjectName.$invalid}")
        label.control-label.muted(for='fProjectName') Project
        .controls
            input.input-xxlarge(name="fProjectName", type='text', placeholder='Project name', ng-model="schedule.projectName", required)
            small.help-inline(ng-messages="scheduleForm.fProjectName.$error")
                div(ng-message="required")
                    | The project name is required.
    .control-group(ng-class="{error: scheduleForm.fWebsiteName.$invalid}")
        label.control-label.muted(for='fWebsiteName') Website name
        .controls
            input.input-xlarge(name="fWebsiteName", type='text', placeholder='Website name', ng-model="schedule.website.name", required)
            small.help-inline(ng-messages="scheduleForm.fWebsiteName.$error")
                div(ng-message="required")
                    | The website name is required if you entered a website link.
    .control-group(ng-class="{error: scheduleForm.fWebsiteURL.$invalid}")
        label.control-label.muted(for='fWebsiteURL') Website URL
        .controls
            input.input-xlarge(name="fWebsiteURL", type='text', placeholder='Website link', ng-model="schedule.website.url", required)
            small.help-inline(ng-messages="scheduleForm.fWebsiteURL.$error")
                div(ng-message="required")
                    | The website link is required if you entered a website name.
    .control-group
        .controls
            button.btn.btn-primary(type='button', name='submit', ng-disabled="scheduleForm.$invalid", ng-click="update()") Save
            button.btn(type='button', name='Cancel', ng-click="cancel()") Cancel

2 个答案:

答案 0 :(得分:0)

这是一个插图,它说明了一个字段是否有效的简单示例取决于另一个字段的存在:

http://plnkr.co/edit/sr3qDWLk7jpEc520qiKs?p=preview

基本上你创建了一个验证函数:

var checkAndSet = function(first, second, scope){
      if ( !_.isUndefined(first) && first !== ''){
        var firstFilledSecondNot =  (_.isUndefined(second) || second === '');
        scope.firstFilledSecondNot = firstFilledSecondNot;
      } else {
        scope.firstFilledSecondNot = false;
      }
   };

此功能只是直接检查第一个输入何时填入,第二个输入是否填充。棘手的部分是您将验证结果放入您的范围以供隐藏输入使用:

<input name="fSecondInput" data-ng-model="firstFilledSecondNot" type="hidden" data-ui-validate="{firstInputFilledInButSecondNot: 'isFirstInputFilledInButSecondNot($value)'}">

正如您所看到的,此输入与“真实”第二个输入具有相同的名称,并具有作为范围的模型

firstFilledSecondNot

您在步骤1中的函数中公开的变量。然后您有

data-ui-validate="{firstInputFilledInButSecondNot: 'isFirstInputFilledInButSecondNot($value)'}"

阻止它获取此值并返回它。验证周期过后,你有

someForm.fSecondInput.$error.firstInputFilledInButSecondNot

你的范围内的对象,这是你想要的。

您可能刚刚使用了两个手表,然后将每个手表的结果放在scope.someForm.fSecondInputObject中,但我发现它更加丑陋:

var checkAndSet = function(first, second, scope){
      if ( !_.isUndefined(first) && first !== ''){
        var firstFilledSecondNot =  (_.isUndefined(second) || second === '');
        scope.someForm.fSecondInput.$error.firstFilledSecondNot = firstFilledSecondNot;
      } else {
        scope.someForm.fSecondInput.$error.firstFilledSecondNot = false;
      }
   };

第二位来自:

http://plnkr.co/edit/W1UW7E2D9DDuOJtL6Jea?p=preview

答案 1 :(得分:0)

根据@baba的评论,我认为我找到了解决问题的方法,这是我实施的逻辑。

我创建了一个负责执行验证的自定义指令。此验证程序称为coBothOrNoneValidator。它需要2个参数,formother-field。最后一个参数是与之比较的字段。

这是我的玉部分:

form.form-horizontal(name="scheduleForm")
    .control-group(ng-class="{error: scheduleForm.fProjectName.$invalid}")
        label.control-label.muted(for='fProjectName') Project
        .controls
            input.input-xxlarge(name="fProjectName", type='text', placeholder='Project name', ng-model="schedule.projectName", required)
            small.help-inline(ng-messages="scheduleForm.fProjectName.$error")
                div(ng-message="required")
                    | The project name is required.
    .control-group(ng-class="{error: scheduleForm.fWebsiteName.$invalid}")
        label.control-label.muted(for='fWebsiteName') Website name
        .controls
            input.input-xlarge(name="fWebsiteName", type='text', placeholder='Website name', ng-model="item.website.name", co-both-or-none-validator, form="scheduleForm", other-field="fWebsiteURL")
            small.help-inline(ng-messages="scheduleForm.fWebsiteName.$error")
                div(ng-message="bothOrNone")
                    | The website name is required if you entered a website link.
    .control-group(ng-class="{error: scheduleForm.fWebsiteURL.$invalid}")
        label.control-label.muted(for='fWebsiteURL') Website URL
        .controls
            input.input-xlarge(name="fWebsiteURL", type='text', placeholder='Website link', ng-model="item.website.url", co-both-or-none-validator, form="scheduleForm", other-field="fWebsiteName")
            small.help-inline(ng-messages="scheduleForm.fWebsiteURL.$error")
                div(ng-message="bothOrNone")
                    | The website link is required if you entered a website name.
    .control-group
        .controls
            button.btn.btn-primary(type='button', name='submit', ng-disabled="scheduleForm.$invalid", ng-click="update()") Save
            button.btn(type='button', name='Cancel', ng-click="cancel()") Cancel

最后,这是我的指令co-both-or-none-validator

angular.module('app').directive("coBothOrNoneValidator", function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, el, attrs, ctrl) {
            var validateBothOrNone = function(value){
                var form = scope[attrs.form];
                var theOther = form[attrs.otherField];
                var isNotValid = (value && (_.isUndefined(theOther.$modelValue) || theOther.$modelValue === ''))
                ctrl.$setValidity('bothOrNone', !isNotValid);
                theOther.$setValidity('bothOrNone', !isNotValid);
                return value;
            };

            ctrl.$parsers.unshift(validateBothOrNone);
        }
    }
})

这是一个非常基本的demo

欢迎任何改进此代码的想法