信用卡到期验证,包含数月和数年的两个单独下拉菜单

时间:2012-12-05 03:52:53

标签: jquery jquery-validate

我正在实施信用卡到期日验证,其中月份和年份分别在下拉列表中;它几乎就在那里,除了一个小的布局问题。

Fiddle

HTML看起来像这样:

<form id="myform">
<table>
<tr>
    <th colspan="2"><label class="secure-section-title" for="ccexp">Expiration date</label></th>
</tr>
<tr>
    <td><select id="ccexp" name="cc_exp_month" class="required creditcardexpiry">
        <option value="01">01</option> ... <option value="12">12</option>
      </select> / <select name="cc_exp_year" class="required creditcardexpiry">
        <option value="2012">12</option> ... <option value="2021">21</option>
    </select></td>
    <td></td>
</tr>
</table>
</form>​

执行验证的JavaScript在这里:

$('#myform').validate({
    errorPlacement: function(error, element) {
        element
            .closest('tr') // take closest parent
            .prev('tr')
            .find('> th')
            .append(error)
        },
        groups: {
            creditcardexpiry: 'cc_exp_month cc_exp_year'
        }
    });

$.validator
    .addMethod('creditcardexpiry', function(value, element) {
        var form = element.form,
        expiry = form['cc_exp_year'].value + form['cc_exp_month'].value,
        date = new Date(),
        month = date.getMonth() + 1,
        now = '' + date.getFullYear() + (month < 10 ? '0' + month : month);

        return expiry > now;
    });

只有当到期日是未来一个月(未来10年的最长期限受下拉限制)时,它才能基本确认。

问题场景是:

  1. 输入过去的日期;将显示错误消息,下拉列表为红色

  2. 通过将年份增加到2014年来修正错误;错误消息消失

  3. 问题是,在再次点击之前,月份下拉列表仍然是红色的!这些字段已分组,因此我预计在解决无效条目时会清除这两个下拉列表。

    我是否忽略了这里显而易见的事情或这是一个错误?

    更新

    这不是关于groups属性的错误,因为这只会确保两个字段中的错误都不会导致两条消息。

2 个答案:

答案 0 :(得分:3)

显然,通过触发下拉事件(默认情况下)重新验证下拉列表。因此,我的解决方案是在所选值发生变化时触发两个下拉列表之间的点击。

var $expiryFields = form.find('.creditcardexpiry');

$expiryFields.on('change', function() {
    // trigger click on the other field to force revalidation
    $expiryFields.not(this).trigger('click');
});

我对这个解决方案不是很满意,所以我希望其他人可以提出更好的解决方案。

Demo

答案 1 :(得分:0)

jQuery.validator.element可用于验证各个元素。实施稍微冗长一点,但更重要的是:

var $expiryFields = $form.find('.creditcardexpiry'),
    $validator = $form.validate();

$expiryFields.change(function() {
    $expiryFields.not(this).each(function () {$validator.element(this)});
});