jQuery UI datepicker change event not caught by KnockoutJS

后端 未结 13 2141
长发绾君心
长发绾君心 2020-11-22 16:16

I\'m trying to use KnockoutJS with jQuery UI. I have an input element with a datepicker attached. I\'m currently running knockout.debug.1.2.1.js and it seems th

相关标签:
13条回答
  • 2020-11-22 16:35

    I solved this problem by changing the order of my included script files:

    <script src="@Url.Content("~/Scripts/jquery-ui-1.10.2.custom.js")"></script>
    <script src="@Url.Content("~/Scripts/knockout-2.2.1.js")"></script>
    
    0 讨论(0)
  • 2020-11-22 16:38

    Alternatively, you can specify this in binding:

    Update:

     function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            current = $(element).datepicker("getDate");
    
        if (typeof value === "string") {            
           var dateValue = new Date(value);
           if (dateValue - current !== 0)
               $(element).datepicker("setDate", dateValue);
        }               
    }
    
    0 讨论(0)
  • 2020-11-22 16:39

    I needed to repeatedly update my data from the server came across this but didn't quite finish the job for my needs sharing below(my date format /Date(1224043200000)/):

    //Object Model
    function Document(data) {
            if (String(data.RedemptionExpiration).indexOf('/Date(') == 0) {
                var newDate = new Date(parseInt(data.BDate.replace(/\/Date\((.*?)\)\//gi, "$1")));
                data.RedemptionExpiration = (newDate.getMonth()+1) +
                    "/" + newDate.getDate() +
                    "/" + newDate.getFullYear();
            }
            this.RedemptionExpiration = ko.observable(data.RedemptionExpiration);
    }
    //View Model
    function DocumentViewModel(){
        ///additional code removed
        self.afterRenderLogic = function (elements) {
            $("#documentsContainer .datepicker").each(function () {
                $(this).datepicker();                   
            });
        };
    }
    

    After the model is formatted correctly for the output I added a template with the documentation knockoutjs:

    <div id="documentsContainer">
        <div data-bind="template: { name: 'document-template', foreach: documents, afterRender: afterRenderLogic }, visible: documents().length > 0"></div>
    </div>
    
    //Inline template
    <script type="text/html" id="document-template">
      <input data-bind="value: RedemptionExpiration" class="datepicker" />
    </script>
    
    0 讨论(0)
  • 2020-11-22 16:40

    Based on Ryan's solution, myDate returns the standard date string, which is not the ideal one in my case. I used date.js to parse the value so it will always return the date format you want. Take a look at this example fiddle Example.

    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            current = $(element).datepicker("getDate");
        var d = Date.parse(value);
        if (value - current !== 0) {
            $(element).datepicker("setDate", d.toString("MM/dd/yyyy"));   
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:40

    Few people asked for dynamic datepicker options. In my case I needed a dynamic date range - so the first input defines the min value of the second and the second sets the max value for the first. I solved it by extending the RP Niemeyer's handler. So to his original:

    ko.bindingHandlers.datepicker = {
        init: function(element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datepickerOptions || {},
                $el = $(element);
    
            $el.datepicker(options);
    
            //handle the field changing by registering datepicker's changeDate event
            ko.utils.registerEventHandler(element, "change", function() {
                var observable = valueAccessor();
                observable($el.datepicker("getDate"));
            });
    
            //handle disposal (if KO removes by the template binding)
            ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
                $el.datepicker("destroy");
            });
    
        },
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                $el = $(element);
    
            //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 = $el.datepicker("getDate");
    
            if (value - current !== 0) {
                $el.datepicker("setDate", value);
            }
        }
    };
    

    I've added two more handlers corresponding to the options I wanted to modify:

    ko.bindingHandlers.minDate = {
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                current = $(element).datepicker("option", "minDate", value);
        }
    };
    
    ko.bindingHandlers.maxDate = {
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
                current = $(element).datepicker("option", "maxDate", value);
        }
    };
    

    And used them like that in my template:

    <input data-bind="datepicker: selectedLowerValue, datepickerOptions: { minDate: minValue()}, maxDate: selectedUpperValue" />       
    <input data-bind="datepicker: selectedUpperValue, datepickerOptions: { maxDate: maxValue()}, minDate: selectedLowerValue" />
    
    0 讨论(0)
  • 2020-11-22 16:41

    I've used a different approach. Since knockout.js doesn't seem to fire the event on change, I've forced the datepicker to call change() for its input once closed.

    $(".date").datepicker({
        onClose: function() {
            $(this).change(); // Forces re-validation
        }
    });
    
    0 讨论(0)
提交回复
热议问题