jQuery यूआई डेटपिकर परिवर्तन घटना नॉकआउट जेएस द्वारा पकड़ा नहीं गया


134

मैं jQuery UI के साथ नॉकआउटJS का उपयोग करने की कोशिश कर रहा हूं। मेरे पास एक इनपुट तत्व है जिसमें एक डेटपिकर संलग्न है। मैं वर्तमान में चल रहा हूं knockout.debug.1.2.1.jsऔर ऐसा लगता है कि बदलाव की घटना को नॉकआउट द्वारा कभी नहीं पकड़ा जा रहा है। तत्व इस तरह दिखता है:

<input type="text" class="date" data-bind="value: RedemptionExpiration"/>

मैंने valueUpdateइवेंट प्रकार बदलने की भी कोशिश की है लेकिन कोई फायदा नहीं हुआ। ऐसा लगता है focusकि मान बदलने से पहले ही क्रोम एक घटना का कारण बनता है , लेकिन IE नहीं करता है।

क्या कुछ नॉकआउट विधि है जो "सभी बाइंडिंग को विद्रोह करती है"? सर्वर पर वापस भेजने से पहले मुझे तकनीकी रूप से केवल मूल्य बदलने की आवश्यकता है। इसलिए मैं उस तरह के वर्कअराउंड के साथ रह सकता था।

मुझे लगता है कि समस्या की तारीख की गलती है, लेकिन मैं यह पता नहीं लगा सकता कि इसे कैसे ठीक किया जाए।

कोई विचार?

जवाबों:


253

मुझे लगता है कि jQuery UI डेटपिकर के लिए, कस्टम बाइंडिंग का उपयोग करना बेहतर होता है, जो कि डेटपेकर द्वारा प्रदान किए गए एपीआई का उपयोग करके डेट ऑब्जेक्ट्स के साथ पढ़ा / लिखेगा।

बंधन ऐसा लग सकता है (मेरे जवाब से यहां ):

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, "changeDate", 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);
        }
    }
};

आप इसका उपयोग इस तरह करेंगे:

<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />

नमूना यहाँ jsField में: http://jsfiddle.net/rniemeyer/NAgNV/


21
मुझे जो पसंद है वह यह है कि आपने इस बाइंडर में कोने नहीं काटे, जैसे डिस्पोजल कॉलबैक। नॉकआउट जे एस महारत के लिए सड़क पर पालन करने के लिए एक ध्वनि उदाहरण!
डेव

2
और क्या डेटपिकर के बारे में एक तत्व है जो कि रात्रिभोज बनाया जाता है ... मेरा मतलब है, डेटपकर एक जीवित हैंडलर के साथ।
फीनिक्स_यूए

6
फीनिक्स_यू: डेटपिकर के लिए गतिशील रूप से बनाई गई वस्तुओं के साथ काम करने के लिए, सुनिश्चित करें कि आईडी या इनपुट का नाम सेट न करें।
जेम्स रीतेग्युई

1
मैं इसका उपयोग कर रहा हूं और यह एक छोटी सी चीज को छोड़कर पूरी तरह से काम कर रहा है - अगर मैं एक ऑब्जर्वेबल के बराबर मिनडेट या मैक्सडेट सेट करता हूं तो यह अपडेट नहीं होता है अगर वह ऑब्जर्वेबल बदल जाता है (उदाहरण के लिए। अगर मेरे पास दो तारीखें हैं जहां अधिकतम तिथि है। पहले का मूल्य दूसरा है, अगर मैं दूसरा अपडेट करता हूं तो यह पहले की अधिकतम तारीख को अपडेट नहीं करता है) यह सवाल stackoverflow.com/questions/14732204/- के
PW Kad

2
घटना नाम की तरह दिखता है गलत है, ko.utils.registerEventHandler (तत्व, "CHANGEDATE", समारोह () - ko.utils.registerEventHandler (तत्व, "परिवर्तन", समारोह () होना चाहिए
एडम Bilinski

13

यहाँ आरपी नीमरियर के उत्तर का एक संस्करण दिया गया है, जो यहाँ पाई गई नॉकआउट सत्यापन लिपियों के साथ काम करेगा: http://github.com/ericmbarnard/Knockout-Validation

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).val());
            if (observable.isValid()) {
                observable($(element).datepicker("getDate"));

                $(element).blur();
            }
        });

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

        ko.bindingHandlers.validationCore.init(element, valueAccessor, allBindingsAccessor);

    },
    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")));
        }

        current = $(element).datepicker("getDate");

        if (value - current !== 0) {
            $(element).datepicker("setDate", value);
        }
    }
};

परिवर्तन किए गए इवेंट हैंडलर में परिवर्तन किए गए मान को पास करने के लिए हैं और पहले सत्यापन लिपियों के लिए तारीख नहीं, तो केवल तिथि निर्धारित करने के लिए यदि यह मान्य है। मैंने मान्यकरण को भी जोड़ा है। यहाँ चर्चा की गई कस्टम बाइंडिंग के लिए आवश्यक है।

http://github.com/ericmbarnard/Knockout-Validation/issues/69

मैंने कुछ चीज़ों के तरीके से होने वाले कुछ अजीबोगरीब परिदृश्यों को खत्म करने के लिए बदलाव पर एक धब्बा के लिए रैंप्रोज़ के सुझाव को भी जोड़ा।


2
मेरे लिए काम करने के लिए प्रतीत नहीं होता है, मुझे टाइपर्रर मिलता है: observable.isModified, लाइन 313 नॉकआउट.वैलिडेशन.जेएस पर एक फ़ंक्शन नहीं है। यहाँ छोटा उदाहरण: frikod.se/~capitol/fel/test.html
अलेक्जेंडर Kjäll

इसे मान्यता पुस्तकालय के साथ काम करने के लिए महत्वपूर्ण पंक्ति है: ko.bindingHandlers.validationCore.init (तत्व, valueAccessor, allBindingsAccessor);
CRice

11

मैंने एक अलग दृष्टिकोण का उपयोग किया है। चूंकि नॉकआउट.जैस परिवर्तन पर घटना को आग नहीं लगता है, मैंने डेटपिकर को एक बार बंद होने के लिए अपने इनपुट में बदलाव () के लिए मजबूर किया है।

$(".date").datepicker({
    onClose: function() {
        $(this).change(); // Forces re-validation
    }
});

1
$ ('। datepicker')। datepicker ({onSelect: function (dateText) {$ ("# date_in")। ट्रिगर ("परिवर्तन");}}};
elsadek

9

हालाँकि इन सभी जवाबों ने मुझे बहुत काम दिया, लेकिन उनमें से किसी ने भी मेरे लिए पूरी तरह से काम नहीं किया। किसी तिथि का चयन करने के बाद, बाइंड किया गया मान अपडेट नहीं होगा। मैं केवल इसे अपडेट करने के लिए प्राप्त कर सकता हूं जब कीबोर्ड का उपयोग करके दिनांक मान को बदलना तब इनपुट बॉक्स से बाहर निकलना। मैंने यह तय किया कि आरपी नीमर के कोड को बढ़ाने के लिए syb के कोड के साथ:

ko.bindingHandlers.datepicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datepickerOptions || {};

            var funcOnSelectdate = function () {
                var observable = valueAccessor();
                observable($(element).datepicker("getDate"));
            }

            options.onSelect = funcOnSelectdate;

            $(element).datepicker(options);

            //handle the field changing
            ko.utils.registerEventHandler(element, "change", funcOnSelectdate);

            //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());
            if (typeof(value) === "string") { // JSON string from server
                value = value.split("T")[0]; // Removes time
            }

            var current = $(element).datepicker("getDate");

            if (value - current !== 0) {
                var parsedDate = $.datepicker.parseDate('yy-mm-dd', value);
                $(element).datepicker("setDate", parsedDate);
            }
        }
    };

मुझे देखने योग्य ($ (तत्व) .datepicker ("getDate")) पर संदेह है; अपने स्वयं के समारोह में बयान और विकल्प के साथ पंजीकृत है।


2
बहुत - बहुत धन्यवाद! मैंने हर उदाहरण की कोशिश की और फिर इसे पृष्ठ के निचले भाग में पाया और यह अंत में काम करता है। मेरे पास बस एक छोटा सा ट्विन है, ताकि बाउंड वैल्यू उसी "सर्वर फ्रेंडली" फॉर्मेट में बनी रहे, जिसमें वह नीचे आया था। आपके फंकऑनसेलेडेट फ़ंक्शन में इसका उपयोग किया गया है: अवलोकनीय ($। Datepicker.formatDate ('yy-mm-dd')। , $ (तत्व) .datepicker ('getDate')));
ब्रुतलदेव

मुझे लगता है कि यदि आप इस onSelectसमारोह को पूरा नहीं करते हैं, तो यह changeघटना नहीं
बढ़ेगी

6

इस लेख के लिए धन्यवाद मुझे यह बहुत उपयोगी लगा।

यदि आप चाहते हैं कि DatePicker बिल्कुल JQuery UI डिफ़ॉल्ट व्यवहार की तरह व्यवहार करे, तो मैं बदले की घटना में तत्व पर एक धब्बा जोड़ने की सलाह देता हूं:

अर्थात

    //handle the field changing
    ko.utils.registerEventHandler(element, "change", function () {
        var observable = valueAccessor();
        observable($(element).datepicker("getDate"));

        $(element).blur();

    });

यह उत्तर पूर्ण नहीं दिखता है? क्या यह @ RPNiemeyer के उत्तर पर टिप्पणी है, या किसी और की है?
rjmunro

3

मैंने अपनी सम्मिलित स्क्रिप्ट फ़ाइलों के क्रम को बदलकर इस समस्या को हल किया:

<script src="@Url.Content("~/Scripts/jquery-ui-1.10.2.custom.js")"></script>
<script src="@Url.Content("~/Scripts/knockout-2.2.1.js")"></script>

मॉडल के साथ भी इसी तरह के मुद्दे को अपडेट नहीं किया जा रहा है, हालांकि इनपुट ने डेटपिकर से सही ढंग से चुनी गई तारीख का प्रतिपादन किया। सुझावों की सूची को शुरू किया .. लेकिन यह निश्चित रूप से मेरी समस्या थी। हम्मम .. मेरे एमवीसी प्रोजेक्ट को लंबे समय तक jquery और jquery UI स्क्रिप्ट के आगे KO स्क्रिप्ट मिली है - अच्छी तरह से परीक्षण करना होगा।
bkwdesign

2

RP Niemeyer के रूप में भी, लेकिन WCF DateTime, Timezones का बेहतर समर्थन और DatePicker का उपयोग करके JQuery की संपत्ति का चयन करें।

        ko.bindingHandlers.datepicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            //initialize datepicker with some optional options
            var options = allBindingsAccessor().datepickerOptions || {};

            var funcOnSelectdate = function () {
                var observable = valueAccessor();
                var d = $(element).datepicker("getDate");
                var timeInTicks = d.getTime() + (-1 * (d.getTimezoneOffset() * 60 * 1000));

                observable("/Date(" + timeInTicks + ")/");
            }
            options.onSelect = funcOnSelectdate;

            $(element).datepicker(options);

            //handle the field changing
            ko.utils.registerEventHandler(element, "change", funcOnSelectdate);

            //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")));
            }

            current = $(element).datepicker("getDate");

            if (value - current !== 0) {
                $(element).datepicker("setDate", value);
            }
        }
    };

का आनंद लें :)

http://jsfiddle.net/yechezkelbr/nUdYH/


1

मुझे लगता है कि यह बहुत आसान हो सकता है: <input data-bind="value: myDate, datepicker: myDate, datepickerOptions: {}" />

इसलिए आपको इनिट फ़ंक्शन में मैनुअल परिवर्तन से निपटने की आवश्यकता नहीं है।

लेकिन इस मामले में, आपके 'myDate' वैरिएबल को केवल दृश्य मान मिलेगा, दिनांक ऑब्जेक्ट नहीं।


1

वैकल्पिक रूप से, आप इसे बाध्यकारी में निर्दिष्ट कर सकते हैं:

अपडेट करें:

 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);
    }               
}

2
यह तब समस्या को हल करता है जब लौटा दिनांक मान स्ट्रिंग प्रारूप में होता है। दिनांक ऑब्जेक्ट के बजाय "2013-01-20T05: 00: 00"। वेब API से डेटा लोड करते समय मैं इसमें भाग गया।
जेम्स रीतेग्युई

0

रयान के समाधान के आधार पर, मायडेट मानक दिनांक स्ट्रिंग लौटाता है, जो मेरे मामले में आदर्श नहीं है। मैंने उस मूल्य को पार्स करने के लिए date.js का उपयोग किया, इसलिए यह हमेशा आपके द्वारा वांछित दिनांक स्वरूप को लौटाएगा इस उदाहरण फिडेल उदाहरण पर एक नज़र डालें ।

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

सर्वर से अपना डेटा बार-बार अपडेट करने के लिए मुझे इसकी आवश्यकता थी, लेकिन नीचे दी गई मेरी जरूरतों को साझा करने के लिए काम पूरा नहीं किया (मेरी तिथि प्रारूप / दिनांक (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();                   
        });
    };
}

आउटपुट के लिए मॉडल को सही ढंग से फॉर्मेट करने के बाद मैंने डॉक्यूमेंटेशन नॉकआउट के साथ एक टेम्प्लेट जोड़ा :

<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

कुछ लोगों ने डायनेमिक डेटपिकर विकल्पों के लिए कहा। मेरे मामले में मुझे एक गतिशील तिथि सीमा की आवश्यकता थी - इसलिए पहला इनपुट दूसरे के न्यूनतम मान को परिभाषित करता है और दूसरा पहले के लिए अधिकतम मूल्य निर्धारित करता है। मैंने आरपी नीमरियर के हैंडलर का विस्तार करके इसे हल किया। तो उसके मूल में:

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);
        }
    }
};

मैंने जिन दो विकल्पों को संशोधित करना चाहा, उनके अनुरूप मैंने दो और हैंडलर जोड़े हैं:

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);
    }
};

और उन्हें मेरे टेम्पलेट में इस तरह इस्तेमाल किया:

<input data-bind="datepicker: selectedLowerValue, datepickerOptions: { minDate: minValue()}, maxDate: selectedUpperValue" />       
<input data-bind="datepicker: selectedUpperValue, datepickerOptions: { maxDate: maxValue()}, minDate: selectedLowerValue" />

0

पिछले उत्तरों में दिए गए कस्टम बाइंडिंग का उपयोग करना हमेशा संभव नहीं होता है। कॉलिंग$(element).datepicker(...) में कुछ महत्वपूर्ण समय लगता है, और यदि आपके पास इस विधि को कॉल करने के लिए उदाहरण के लिए, कुछ दर्जनों, या यहां तक ​​कि सैकड़ों तत्व हैं, तो आपको इसे "आलसी" करना होगा, अर्थात मांग पर।

उदाहरण के लिए, दृश्य मॉडल को आरंभीकृत किया जा सकता है, input एस को डीओएम में डाला जा , लेकिन संबंधित तारीखों को केवल तब आरंभ किया जाएगा जब कोई उपयोगकर्ता उन्हें क्लिक करेगा।

तो, यहाँ मेरा समाधान है:

एक कस्टम बाइंडिंग जोड़ें जो एक नोड को मनमाना डेटा संलग्न करने की अनुमति देता है:

KO.bindingHandlers.boundData = {
  init: function(element, __, allBindings) {
    element.boundData = allBindings.get('boundData');
  }
};

बाध्यकारी का उपयोग करने के लिए अवलोकनीय का उपयोग करने के लिए input's मान:

<input type='text' class='my-date-input'
       data-bind='textInput: myObservable, boundData: myObservable' />

और आखिरकार, डेटपिकर को इनिशियलाइज़ करते समय, इसका उपयोग करें onSelectविकल्प:

$('.my-date-input').datepicker({
  onSelect: function(dateText) {
    this.myObservable(dateText);
  }
  //Other options
});

इस तरह, हर बार जब उपयोगकर्ता तारीख के साथ तारीख बदलता है, तो इसी नॉकआउट का अवलोकन भी अद्यतन किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.