【问题标题】:Compare observable dates with knockout and jQuery Validation将可观察日期与淘汰赛和 jQuery 验证进行比较
【发布时间】:2015-10-18 01:02:33
【问题描述】:

是否可以将日期与 Knockout observables 和 jQuery Validation 进行比较?我有一个 StartDate 和一个 EndDate,都是可观察的。我想验证 EndDate 是否总是大于 StartDate。

我已经尝试过 addMethod 功能,但我似乎无法传入 self.StartDate。 addMethod 似乎不接受 KO observables,所以我必须传入字符串 ID“#StartDate”。

$.validator.addMethod("dateGreater", function(value, element, params){
       var endDate = new Date(value); // this returns incorrect date.
       var startDate = new Date($(params).val()); 

       return this.optional(element) || startDate < endDate;
   }, "The End Date must be greater thatn the Start Date.");

此代码的问题在于,当用户使用 DatePicker 选择日期时,EndDate 返回上一个日期,而不是当前选择的日期,并且由于 StartDate 不是一个正在验证的可观察对象,如果用户更改它,验证不会触发。

我想我的问题确实是,这可以通过 jQuery 验证来完成,还是应该使用 Knockout-validation?

我创建了一个简单的 jsfiddle,它显示了我想要完成的工作。 http://jsfiddle.net/kahanu/htqfa1qw/6/

【问题讨论】:

  • 我使用 jquery-validation 没有敲除验证,所以我不确定你是否需要立即改变你的方法 - 应该能够弄清楚!几个想法:如果用户可以编辑开始日期,您可以将其绑定到可观察对象以帮助验证过程吗?以及您使用什么日期时间小部件 - 有时您需要使用更改事件戳这些小部件,以告诉 KO 更新 observable。
  • StartDate 和 EndDate 都已经是 observables 了,抱歉,我会编辑我的帖子,我应该把它包括在内。我正在使用 bootstrap-datepicker.js 小部件。但是这个 addMethod 不接受一个 observable 作为参数,我试过了。这就是为什么我需要求助于元素 ID 方法,但它不起作用。
  • 从广义上讲,我发现将 jquery-validation 保持在 KO 之外效果很好。在这种情况下,我会将输入与相当正常的 jquery 验证方法进行比较。您不会在这里失去任何魔力,因为 jquery-validation 负责自己的更改事件跟踪。然后通常还需要修复将日期时间小部件推送到您的视图模型中。我只是在做一个小提琴来展示这种方法。是这个版本的 bootstrap-datetime 吗? eonasdan.github.io/bootstrap-datetimepicker
  • 啊实际上你下面的小提琴很好,我有它在里面工作......会发布答案。

标签: javascript jquery validation knockout.js


【解决方案1】:

这个答案遵循将 jquery-validation 保持在 KO 之外的方法。我认为这没关系,因为你不会失去任何魔法; jquery-validation 有自己的跟踪变化的框架,它把 KO 和 jquery-validation 分开,这很简单。

这是你的小提琴,应用了这种方法:

http://jsfiddle.net/htqfa1qw/7/

修复如下:

  1. jquery-validation 需要输入元素中的名称

  2. 然后这些名称与规则对象中的键对应。

  3. 参数传递很奇怪,文档没有很好地解释它!

所以你的规则对象现在看起来像这样:

    EndDate: {
        required: true,
        dateGreater: {
            param: "StartDate"
        }
    }

也就是说我们希望&lt;input name="EndDate"&gt; 大于&lt;input name="StartDate"&gt;

然后我们修改规则,让它直接从 DOM 中获取值,而不需要通过 KO:

var start = new Date($("[name="+param+"]").val());

如果你确实想通过 KO 传递你描述的 observable 来做到这一点,那么你可以这样做:

http://jsfiddle.net/htqfa1qw/9/

在应用之前实例化您的数据模型:

var dm = new DataModel();
ko.applyBindings(dm);

然后更改验证规则以通过参数查找方法,并调用它:

$.validator.addMethod("dateGreater", function (endDate, element, param) {
    var end= new Date(endDate);
    var start = new Date(dm[param].call());
    return this.optional(element) || start < end;
}, "Start Date must be less than End Date.");

(对 cme​​ts 的引用)一旦它与 bootstrap-datetime 小部件一起工作,您需要注意小部件如何更改输入值,以及它更改值的方法如何与 jquery-validation 交互框架和 KO 框架,两者都依赖于变更事件。

在您的小提琴中,问题似乎是在小部件成功将新值加载到输入之前,jquery-validation 被旧日期值触发。因此,您会看到对旧值进行验证...快速修复似乎是在您已经拥有的事件处理程序中调用 jquery-validation 的 valid() 方法来触发手动验证:

    $el.datepicker(options).on("changeDate", function (ev) {
        var observable = valueAccessor();
        observable(ev.date);
        $(this).datepicker('hide');

        // Poke jquery validation to validate this new value.
        $("#date-form").valid();
    });

在这里演示:

http://jsfiddle.net/htqfa1qw/12/

在这个小提琴中有一些console.logs,你可以跟踪序列:

  1. 使用旧值调用验证(“开始日期...”日志语句)
  2. 您的事件处理程序使用新值启动(“changeDate”日志语句)
  3. 我们手动调用 valid() 并使用新值调用验证(第二个“开始日期...”日志语句)

【讨论】:

  • 太棒了!抱歉,我花了一段时间才回复。灭火。我喜欢这两种方法。我真的很喜欢 dm[param]call(),但我不太确定参数是否正确传递。我看我没有。你救了我。
  • 还有一点,如果在 jQuery 验证规则中使用 HTML 输入元素上的“必需”属性,是否需要它?
  • 好的,虽然这适用于 jsfiddle,但它不适用于 Bootstrap DatePicker。我更新了小提琴以使用日期选择器,但它不起作用。我再次确定我不知道配置问题。有什么建议? jsfiddle.net/kahanu/htqfa1qw/11。请注意,当您使用日期选择器更改日期时,console.log 显示的结束日期不正确。
  • 是的,您可以删除所需的属性。有多种应用方法,但您只需要一种 - 这是一个很好的低调:stackoverflow.com/questions/14375707/…
  • 很高兴你一切顺利。所以小部件的问题可能是小部件干扰了 KO 的数据绑定......通常当小部件设置一个值时,更改事件被压扁,因此视图模型没有得到更新。您经常不得不求助于一些手动代码将值推回 KO,或者探索自定义绑定的世界。我使用带有 KO 的 jquery-validation 的引导日期选择器,并且已经编写了一些手动代码,所以我会看看你的小提琴,看看我是否可以让它工作......
猜你喜欢
  • 1970-01-01
  • 2017-12-01
  • 1970-01-01
  • 2012-11-02
  • 2012-07-07
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
相关资源
最近更新 更多