[jquery-ui] KnockoutJS에 의해 잡히지 않는 jQuery UI 날짜 선택기 변경 이벤트

jQuery UI에서 KnockoutJS를 사용하려고합니다. 날짜 선택기가 첨부 된 입력 요소가 있습니다. 현재 실행 중이며 knockout.debug.1.2.1.js변경 이벤트가 Knockout에 걸리지 않는 것 같습니다. 요소는 다음과 같습니다.

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

valueUpdate이벤트 유형 변경을 시도 했지만 아무 소용이 없습니다. Chrome이 focus값을 변경하기 직전 에 이벤트를 일으키는 것처럼 보이지만 IE는 그렇지 않습니다.

“모든 바인딩을 리 바인딩하는”녹아웃 방법이 있습니까? 기술적으로 서버로 다시 보내기 전에 변경된 값만 있으면됩니다. 그래서 나는 그런 종류의 해결 방법으로 살 수있었습니다.

문제는 datepicker의 잘못이라고 생각하지만이 문제를 해결하는 방법을 알 수 없습니다.

어떤 아이디어?



답변

jQuery UI datepicker의 경우 datepicker에서 제공하는 API를 사용하여 Date 객체로 읽고 쓰는 사용자 정의 바인딩을 사용하는 것이 좋습니다.

바인딩은 다음과 같습니다 ( 여기서 내 대답 에서 ).

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

여기 jsFiddle의 샘플 : http://jsfiddle.net/rniemeyer/NAgNV/


답변

다음은 RP Niemeyer의 답변 버전입니다. 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);
        }
    }
};

변경 이벤트 핸들러는 날짜가 아닌 입력 한 값을 유효성 검증 스크립트에 먼저 전달한 다음 유효 할 경우 관찰 가능 항목으로 날짜 만 설정하도록 변경됩니다. 또한 여기에 설명 된 사용자 정의 바인딩에 필요한 validationCore.init를 추가했습니다.

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

또한 변경에 대한 rpenrose의 제안을 추가하여 성가신 날짜 선택기 시나리오를 제거합니다.


답변

다른 접근법을 사용했습니다. knockout.js는 변경시 이벤트를 발생시키지 않는 것이므로 datepicker가 입력을 닫을 때 change ()를 호출하도록 강요했습니다.

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


답변

이 모든 대답이 저에게 많은 작업을 절약 해 주었지만 그 중 어느 것도 나를 위해 완전히 효과가 없었습니다. 날짜를 선택한 후에는 바인드 된 값이 업데이트되지 않습니다. 키보드를 사용하여 날짜 값을 변경 한 다음 입력 상자를 클릭 할 때만 업데이트 할 수 있습니다. 나는 이것을 얻기 위해 syb의 코드로 RP Niemeyer의 코드를 보강하여 이것을 고쳤다.

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

observable ($ (element) .datepicker ( “getDate”)); 자체 기능으로 문장을 작성하고 options.onSelect에 등록하면 트릭이 수행됩니까?


답변

이 기사에 감사드립니다. 매우 유용하다는 것을 알았습니다.

DatePicker가 JQuery UI 기본 동작과 똑같이 동작하도록하려면 change 이벤트 핸들러에서 요소에 흐림 효과를 추가하는 것이 좋습니다.

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

        $(element).blur();

    });


답변

포함 된 스크립트 파일의 순서를 변경하여이 문제를 해결했습니다.

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


답변

RP Niemeyer와 동일하지만 WCF DateTime, 시간대 및 DatePicker onSelect 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/