web-dev-qa-db-ja.com

jquery-ui datepickerを使用したknockoutjsデータバインド

jQuery UI datepickerを使用しています。その背後のHTML入力フィールドは現在、dependentObservableとして KnockoutJS に接続されていますが、その値がビューモデルで設定されると、datepickerは形式を失います。

どうすればフォーマットを失うことはありませんか? viewModelが jQuery datepickerであることを知りたくないのですが。

39

Datepicker APIを使用してフィールドに日付を設定し、日付を適切に読み取ることでオブザーバブルの値を設定するカスタムバインディングを作成できます。

カスタムバインディングは次のようになります。

_ko.bindingHandlers.datepicker = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var options = allBindingsAccessor().datepickerOptions || {},
            $el = $(element);

        //initialize datepicker with some optional options
        $el.datepicker(options);

        //handle the field changing
        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),
            current = $el.datepicker("getDate");

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

次のように使用します。

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

datepickeroptionsはオプションであり、datepicker()呼び出しに渡すものを含めることができます。

また、これは、日付にオブザーバブルを使用していることを前提としています。観察不可能な一方向のバインディングを行う場合、バインディングはもう少し作業を行う必要がありますが、それはほとんどありません。

ここのサンプル: http://jsfiddle.net/rniemeyer/NAgNV/

79
RP Niemeyer

上記の答えとしてマークされたRP Niemeyerのコードを使用しましたが、使用して以来、いくつかの小さな変更を加えました。ここに投稿すると思いました。たぶん他の人を助けるでしょう。ほとんど同じですが、唯一の違いは、ページの読み込み時に要素に値がある場合、その値を保持することです。また、jQueryが行う必要のある$(element)の処理が少なくなるように、$elemを変数にしました。

ko.bindingHandlers['jqDatePicker'] = {
    'init': function(element, valueAccessor, allBindingsAccessor) {
        /* Initialize datepicker with some optional options */
        var options = allBindingsAccessor().jqDatePickerOptions || {},
            prop = valueAccessor(),
            $elem = $(element);

        prop($elem.val());

        $elem.datepicker(options);

        /* Handle the field changing */
        ko.utils.registerEventHandler(element, "change", function () {
            prop($elem.datepicker("getDate"));
        });

        /* Handle disposal (if KO removes by the template binding) */
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $elem.datepicker("destroy");
        });
    },
    'update': function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            $elem = $(element),
            current = $elem.datepicker("getDate");

        if (value - current !== 0) {
            $elem.datepicker("setDate", value);
        }
    }
};
6
Evan Larsen

DateFormatオプションを使用してコードで動作するように、RP Niemeyerのコードをわずかに編集する必要がありました。

$(element).datepicker("getDate")

$(element).val()

したがって、フォーマットされた日付のバージョンは、内部で正しく渡されました。

6
OddEssay

これが私の特定の状況に合ったものです。デフォルトの日時シリアライザーがISO 8601でレンダリングするMVCの新しい十分なバージョンを実行しています(JSON Datesである悪夢に加えて、JSON.NETおよびASPを参照してください)。 NET Web API)。私のバインディングは日付ピッカーに直接書き込みませんが、代わりに入力タグの「値」属性に書き込みます。

また、注意して、私は date.js を使用しています

ko.bindingHandlers.dateValue = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = valueAccessor(),
            allBindings = allBindingsAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
        var pattern = allBindings.datePattern || 'MM/dd/yyyy';
        var date = Date.parse(valueUnwrapped)
        $(element).val(date.toString(pattern));
    },

    init: function(element, valueAccessor, allBindingsAccessor) {
        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function () {
            var observable = valueAccessor();
            var date = Date.parse($(element).val());
            observable(date.toString("yyyy-MM-ddThh:mm:ss"));
        });
    }
}

バインドは次のようになります。

<input class="date" type="text" data-bind="dateValue: SomeViewModelDate" />

そして、日付ピッカーをオンにするJavaScriptコード:

$(document).ready(function () {
    $('.date').datepicker({ dateFormat: "mm/dd/yy" });
});
2
viggity

上記の日付ピッカーのサンプルでは、​​ユーザーが日付ピッカーコントロールから新しい日付を選択すると、ビューモデルの日付の形式を [〜#〜] wcf [〜#〜] 形式からJavaScript日付形式に変更します。

私の場合、日付をWCFサービスに返していましたが、デシリアライズされたJavaScriptの日付を受け入れず、WCF形式の日付が必要でした。上記のスクリプトを変更して、日付をWCF形式でビューモデルに保存し、その形式でサーバーに返送できるようにしました。

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).datepicker("getDate"));
            // store the date in 'WCF String format"
            var tempdate=$(element).datepicker("getDate");
            var tempdatestr="/Date("+tempdate.getTime()+")/";
            observable(tempdatestr);
        });
        //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);
        }
    }
};
1
Russellg

DependentObservable内で日付を(mm/dd/yyyyに)書式設定することは、私がどうすればいいのかと思っていたものです。あなたが助けることができるなら、私は私のコードの少しを投稿します、ピーター・モーテンセンおよび/またはnEEBz。

    <div data-bind="with: technology">  
        <div class="titleblock">
            <label><b>End of Life Date</b></label> 
            <Input  type="text" class="ui-datepicker" id="datepicker" data-bind="value: END_OF_LIFE_DATE"/>
        </div>       
    </div>

viewModelで-technologydetail.js:

var technology = ko.observable();

アクティベート中:

return dataContext.getTechnologyById(currentTechnologyId, technology);

これにより、テキストボックスに次のような日付が表示されます:2014年1月29日水曜日19:00:00 EST 2014年1月29日:このdatepickerオプション-dateFormat: "mm/dd/yy"を使用していますが、表示される初期値には影響しません。

モーメントを使用してフォーマットすることができ、現在のデータベース値を表示するのにうまく機能しますが、SAVEで更新されなくなるため、observableへのバインディングを解除しているようです。

<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: moment(END_OF_LIFE_DATE()).format('MM/DD/YYYY')" />
0
Debbie A

1つの解決策は、dependentObservable関数内で日付を自分でフォーマットすることです。したがって、関数でreturn viewModel.someOtherObservable()のようなものを返す必要があります。戻り値をフォーマットします。

コードを含めれば、さらに説明できます。

0
neebz