自定义 Flatpickr Knockout 绑定

Custom Flatpickr Knockout binding

我正在尝试为 Flatpickr but having no luck. I've tried tweaking the code from the accepted answer here 创建一个敲除绑定,但没有成功。 Flatpickr 已初始化,但它似乎没有使用我设置的默认选项,而且绑定的更新部分根本不起作用。

我的代码如下。我会创建一个 jsFiddle 但它在工作中被阻止了..

ko.bindingHandlers.datetimepicker = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var options = allBindingsAccessor().datetimepickerOptions || { dateFormat: 'm-d-Y', enableTime: true };
    var $el = $(element);

    $(element).flatpickr(options);

    //handle the field changing by registering datepicker's changeDate event
    ko.utils.registerEventHandler(element, "onChange", function () {
      var observable = valueAccessor();
      observable($el.val());
    });

    //handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
      $el.flatpickr("destroy");
    });

    $el.val(new Date(ko.utils.unwrapObservable(valueAccessor())));
  },
  update: function (element, valueAccessor, allBindingsAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor());
    var $el = $(element);

    // handle json date from microsoft
    if (String(value).indexOf('/Date(') == 0) {
      value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "")));
    }

    var current = new Date($el.val());

    if (value - current !== 0) {
      $el.flatpickr('setDate', value);
    }
  }
};

编辑

关于我的情况的更多信息。我有一个顶部带有寻呼机按钮的页面,这些按钮在我的视图模型中循环通过一个数组。每次我翻页时,都会将 displayedRecord 属性 设置为数组中的 next/prev 项,并且所有编辑字段都绑定到 displayedRecord 属性。这适用于我的所有输入,除了使用@atitsbest 提供给我的 datetimepicker 绑定的输入。

第一次填充 datetimepicker 字段,但是一旦我翻过它们,该记录的视图模型 属性 不知何故被设置为 null。

编辑 2

终于成功了。这是最终产品。最终删除了 init 函数中的订阅,因为它在尝试将其可观察到的值设置为 null 时导致错误。还为用户添加了 flatpickr 包装功能,以提供他们自己的用于清除、切换等的按钮。

ko.bindingHandlers.flatpickr = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var options = $.extend({
      dateFormat: 'm/d/Y H:i',
      enableTime: true,
      time_24hr: true,
      minuteIncrement: 1
    }, allBindingsAccessor().flatpickrOptions);
    var $el = $(element);
    var picker;

    if (options.wrap) {
      picker = new Flatpickr(element.parentNode, options);
    } else {
      picker = new Flatpickr(element, options);
    }

    // Save instance for update method.
    $el.data('datetimepickr_inst', picker);

    // handle the field changing by registering datepicker's changeDate event
    ko.utils.registerEventHandler(element, "change", function () {
      valueAccessor()(picker.parseDate($el.val()));
    });

    // handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
      $el.flatpickr("destroy");
    });
  },
  update: function (element, valueAccessor, allBindingsAccessor) {
    // Get datepickr instance.
    var picker = $(element).data('datetimepickr_inst');

    picker.setDate(ko.unwrap(valueAccessor()));
  }
};

我创建了一个 jsfiddle 并对您的绑定做了一些更改:

  • 将事件名称从 "onChange" 更改为 "change";现在它开火了。
  • 创建了一些默认选项,即使设置了自定义选项也是如此;对于默认 dateFormat.
  • 很有用
  • 将 "update" 函数替换为订阅以更新 可观察;.
  • 绑定值现在总是一个日期。

新绑定:

ko.bindingHandlers.datetimepicker = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    var options = $.extend({
        dateFormat: 'm-d-Y H:i',
        enableTime: true
      }, allBindingsAccessor().datetimepickerOptions),
      $el = $(element),
      picker = new Flatpickr(element, options),
      observable = valueAccessor();

    //handle the field changing by registering datepicker's changeDate event
    ko.utils.registerEventHandler(element, "change", function() {
      observable(picker.parseDate($el.val()));
    });

    //handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
      $el.flatpickr("destroy");
    });

    observable.subscribe(function(newVal) {
      $el.val(picker.formatDate(options.dateFormat, newVal));
    });

    picker.setDate(ko.unwrap(observable));
  }
};

希望对您有所帮助。

更新

为了处理分页,我更改了绑定。这是更新后的 jsfiddle,用于测试与分页方案的绑定。 这里是新的绑定代码:

ko.bindingHandlers.datetimepicker = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    var options = $.extend({
          dateFormat: 'm-d-Y H:i',
          enableTime: true
        },
        allBindingsAccessor().datetimepickerOptions),
      $el = $(element),
      picker = new Flatpickr(element, options);

    // Save instance for update method.
    $el.data('datetimepickr_inst', picker);

    // handle the field changing by registering datepicker's changeDate event
    ko.utils.registerEventHandler(element, "change", function() {
      valueAccessor()(picker.parseDate($el.val()));
    });

    // handle disposal (if KO removes by the template binding)
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
      $el.flatpickr("destroy");
    });

    // Update datepicker with new value from observable
    valueAccessor().subscribe(newVal => $el.val(picker.formatDate(options.dateFormat, newVal)));
  },
  update: function(element, valueAccessor, allBindingsAccessor) {
    // Get datepickr instance.
    var picker = $(element).data('datetimepickr_inst');

    picker.setDate(ko.unwrap(valueAccessor()));
  }
};

希望对您有所帮助。