当 jQuery 日期选择器打开时,挖空更改会中断日期选择器

Knockout change while jQuery Datepicker is open breaks Datepicker

本文关键字:日期 选择器 中断 jQuery      更新时间:2023-09-26

我已经设置了一个jsFiddle来演示我的问题。

我在做什么

我正在使用带有jQuery DatepickerKnockout,如此问题所示。

我的模型包含一个observableArray,其中包含具有日期属性的对象。Knockout 为每个对象呈现一个<input type="text">,并使用 RP Niemeyer 的 datepicker 绑定将值绑定到日期。

出了什么问题:

如果用户在 KNOCKOUT 的模型更改(例如,添加新项)时打开了日期选取器,则日期选取器将停止正常工作。据我所知,在日期选取器打开时创建的最后一个<input type="text">成为新的日期选取器目标。我需要修复绑定,以免发生这种情况

示例 HTML

<ul data-bind="foreach: dateBoxes">
    <li>
        <span data-bind="text: index"></span>
        <input type="text" data-bind="datepicker: date"/>
    </li>
</ul>

示例 Javascript

ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        //initialize datepicker with some optional options
        var options = allBindingsAccessor().datepickerOptions || {};
        $(element).datepicker(options);
        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function() {
            var observable = valueAccessor();
            observable($(element).datepicker("getDate"));
        });
        //handle disposal (if KO removes by the template binding)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).datepicker("destroy");
        });
    },
    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        //handle date data coming via json from Microsoft
        if (String(value).indexOf('/Date(') == 0) {
            value = new Date(parseInt(value.replace(/'/Date'((.*?)')'//gi, "$1")));
        }
        var current = $(element).datepicker("getDate");
        if (value - current !== 0) {
            $(element).datepicker("setDate", value);
        }
    }
};
var model;
var id = 0;
function DateBox(d) {
    var self = this;
    self.date = ko.observable(d);
    self.index = ko.observable(id++);
}
function Model() {
    var self = this;
    self.dateBoxes = ko.observableArray([]);
    self.changeCount = function() {
        if (self.dateBoxes().length < 2) {
            self.dateBoxes.push(new DateBox(new Date()));
        } else if (self.dateBoxes().length > 1) {
            self.dateBoxes.splice(0,1);
        }
    }
    self.tick = function() {
        self.changeCount();
        setTimeout(function() {
            self.tick();
        }, 5000);
    }
    self.tick();
}
model = new Model();
ko.applyBindings(model);

注意:此答案不完整。但是,由于它太大而无法发表评论,并且可能对(解决方案)有所帮助,无论如何,我冒昧地将其作为答案发布。任何可以完成此答案的人都被邀请通过编辑或衍生到另一个更好的答案来完成。


似乎破坏派对的事情(取自文档,强调我的):

当绑定首次应用于元素时,将调用一次,每当关联的可观察量更改值时,将再次调用此值。

如果我在第一次更新中阻止update进行datepicker调用,则日期选择器将不再中断(但确实会出现其他问题)。对于init,我在末尾添加了这一行:

element.isFirstRun = true;

然后,update方法将在datepicker调用之前执行以下操作:

if (element.isFirstRun) {
    $(element).val(value);
    element.IsFirstRun = false;
    return;
}    

请参阅此更新的小提琴以获取结果,它们是:

  • 提到的场景现在更新了正确的文本框(一件好事);
  • 初始值现在是一个更详细的 DateTime 字符串,并在更新后保持这种状态(有点不好);

希望这将有助于达成更完整的解决方案。