jQuery datepicker - Knockout绑定设置初始日期

本文关键字:日期 设置 绑定 datepicker Knockout jQuery | 更新日期: 2023-09-27 18:05:55

我使用的是带有自定义绑定的jQuery日期拾取器(在结合了来自各地的几个示例之后)。说清楚;更改日期时一切正常,我的问题在于用户不更改日期的情况。这意味着日期拾取器的值应该是输入日期拾取器和文本框元素的初始日期。

这是MVC,所以我使用一个普通的c# DateTime对象。注意这个DateTime是可空的,所以是一个DateTime?对象。

以这个场景为例:

用户加载网页,我的MVC模型被发送到该页面。我的模型看起来像这样(JSON格式):

{
    "User": "Christian Haase",
    "Username": "ChristianH",
    "Date": "/Date({som-random-millisecond-number})/"
}

注意:这不是复制粘贴的,所以有些东西可能看起来有点像这个Date值。

让我们做一个简单的网页让用户改变这个值:

<p data-bind="text: User" ></p>
<input data-bind="value: Username" />
<input data-bind="datepicker: Date, datepickerOptions: { dateFormat: 'dd/mm/yy' }" />

非常简单,但是从标记方面来说这应该足够了。让我们把knockout和日期选择器绑定连接起来。

<script type="text/javascript">
    $(document).ready(function(){
        // Loading the viemodel from MVC (the JSON object)
        var vm = ko.mapping.fromJSON('@Model');
        // Adding the datepicker binding!
        ko.bindingHandlers.datepicker = {
            init: function (element, valueAccessor, allBindingsAccessor) {
                // Getting the datepickerOptions value applied to the binding, if any. Else just an empty object.
                var options = allBindingsAccessor().datepickerOptions || {};
                // Instantiating the datepicker with the options object
                $(element).datepicker(options);
                // Listen for any changes in the element
                ko.utils.registerEventHandler(element, "change", function(){
                    var observable = valueAccessor();
                    var value = $(element).val();
                    // Check to see whether the element.val() is empty or not
                    if(!value){
                        // If empty, I want the observable to hold value 'null'
                        observable(null);
                    } else{
                        // Converting the string '01/09/2016' to an actual JS Date object and settings the observable to that value
                        var date = convertStringToDate(value);
                        observable(date);
                    }
                });
            },
            update: function(element, valueAccessor){
                // Get the value from the viewmodel
                var value = ko.unwrap(valueAccessor());
                // Get the observable
                var observable = valueAccessor();
                // Check whether the value is null or not
                if(value === null){
                    // If the value is null, set the value of the element equal to an empty string
                    $(element).val('');
                }
                else{
                    // If the value is not null (is it something) set the new date on the datepicker.
                    // Parse the JSON date string ('/Date({some-random-millisecond})')
                    var date = parsejsonDateString(value);
                    // Set the new JS Date object to the datepickers 'setDate' function
                    $(element).datepicker('setDate', value);
                }
            }
        }
        vm.save = function(){
            // Function to save the changes made to the object
            // Loggign the date to see the value that'll be sent to the MVC controller
            console.log(vm.Date());
            ....
            // The ajax request is irrelevant
        }
        ko.applyBindings(vm);
    });
</script>

现在,您可能注意到我正在执行一些调用来操作Date对象、JSON Date字符串('/Date({some-random-millisecond})/')和原始字符串中的日期('01/09/2016'),我怀疑其中一个可能会干扰日期。下面是这些函数:

var jsonDateRE = /^'/Date'((-?'d+)('+|-)?('d+)?')'/$/;
var parseJsonDateString = function (value) {
    var arr = value && jsonDateRE.exec(value);
    if (arr) {
        return new Date(parseInt(arr[1]));
    }
    return value;
};
var convertStringToDate = function (stringDate) {
    if (stringDate != null || stringdate || string != "") {
        var from = stringDate.split("/");
        return new Date(from[2], from[1] - 1, from[0]);
    }
    return "";
}

我很不清楚当日期选择器初始化时实际发生了什么,但如果用户点击"保存"而不更改初始日期,我的控制台说;无效的日期。另一方面,如果用户确实从日期选择器更改了日期,则一切都按预期工作。

我不确定如何实际使这个日期选择器绑定工作,所有可能的指导是高度赞赏的!

请让我知道,如果你需要进一步的解释或代码(虽然我没有真正看到其他相关的代码比这)。我很乐意提供所有需要的信息。

jQuery datepicker - Knockout绑定设置初始日期

我整理了一个小例子。注意,我添加了一个显示Date值的span。这是一种简单的方法,可以看到它在启动时是什么,以及当您选择不同的值时它会变成什么。在这个例子中,似乎没有任何非日期类的东西,但是您的系统中可能有不同的条件。

还请注意,我将parsejsonDateString的大写改为parseJsonDateString。如果你的代码是这样的,那将是一个问题(但是你应该在控制台中看到错误)。

var jsonDateRE = /^'/Date'((-?'d+)('+|-)?('d+)?')'/$/;
var parseJsonDateString = function (value) {
    var arr = value && jsonDateRE.exec(value);
    if (arr) {
        return new Date(parseInt(arr[1]));
    }
    return value;
};
var convertStringToDate = function (stringDate) {
    if (stringDate != null || stringdate || string != "") {
        var from = stringDate.split("/");
        return new Date(from[2], from[1] - 1, from[0]);
    }
    return "";
};
ko.bindingHandlers.datepicker = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    // Getting the datepickerOptions value applied to the binding, if any. Else just an empty object.
    var options = allBindingsAccessor().datepickerOptions || {};
    // Instantiating the datepicker with the options object
    $(element).datepicker(options);
    // Listen for any changes in the element
    ko.utils.registerEventHandler(element, "change", function() {
      var observable = valueAccessor();
      var value = $(element).val();
      // Check to see whether the element.val() is empty or not
      if (!value) {
        // If empty, I want the observable to hold value 'null'
        observable(null);
      } else {
        // Converting the string '01/09/2016' to an actual JS Date object and settings the observable to that value
        var date = convertStringToDate(value);
        observable(date);
      }
    });
  },
  update: function(element, valueAccessor) {
    // Get the value from the viewmodel
    var value = ko.unwrap(valueAccessor());
    // Get the observable
    var observable = valueAccessor();
    // Check whether the value is null or not
    if (value === null) {
      // If the value is null, set the value of the element equal to an empty string
      $(element).val('');
    } else {
      // If the value is not null (is it something) set the new date on the datepicker.
      // Parse the JSON date string ('/Date({some-random-millisecond})')
      var date = parseJsonDateString(value);
      // Set the new JS Date object to the datepickers 'setDate' function
      $(element).datepicker('setDate', value);
    }
  }
}
ko.applyBindings({
  User: ko.observable('1'),
  Username: ko.observable('The guy'),
  Date: ko.observable('?')
});
<link href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/css/bootstrap-datepicker.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.4/js/bootstrap-datepicker.min.js"></script>
<p data-bind="text: User" ></p>
<input data-bind="value: Username" />
<input data-bind="datepicker: Date, datepickerOptions: { dateFormat: 'dd/mm/yy' }" />
<div>Date as text: <span data-bind="text:Date"></span></div>