23

この質問は、jquery-ui datepicker を使用したノックアウト js データバインドに似ていますが、jQueryUI の datepicker の代わりに、 Bootstrap の datepickerの 1 つを使用したいと思います。

Bootstrap datepicker の API は jquery-ui とは異なり、knockout.js で動作させるのに頭を悩ませています。試してみるために jsFiddle を作成しました。

ブートストラップの日付ピッカーは、日付を個別に保存しないため、はるかに簡単に使用できるようです。ただし、jsFiddle が Bootstrap datepicker ウィジェットを knockout.js で使用する適切な方法であるかどうかを知りたいです。

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

      ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).datepicker("destroy");
        });
    },
    update: function(element, valueAccessor) {
    }
};
4

5 に答える 5

41

使用している日付ピッカーでこれを達成する方法のサンプルを次に示します。

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

      //when a user changes the date, update the view model
      ko.utils.registerEventHandler(element, "changeDate", function(event) {
             var value = valueAccessor();
             if (ko.isObservable(value)) {
                 value(event.date);
             }                
      });
    },
    update: function(element, valueAccessor)   {
        var widget = $(element).data("datepicker");
         //when the view model is updated, update the widget
        if (widget) {
            widget.date = ko.utils.unwrapObservable(valueAccessor());
            if (widget.date) {
                widget.setValue();            
            }
        }
    }
};

破壊機能がないように見えたので、その部分を削除しました。これは、ユーザーが日付を変更したときに、ウィジェットchangeDateイベントを処理してビュー モデルを更新します。このupdate関数は、ウィジェットを更新するためにビュー モデルが変更されたときに処理します。

値を観察できないものにバインドしたい場合は、もう少しコードが必要です。それがあなたがサポートする必要があるものかどうか教えてください。

http://jsfiddle.net/rniemeyer/KLpq7/

于 2012-06-20T15:17:04.257 に答える
6

受け入れられた回答は、現在のバージョンの日付ピッカーでは機能しませんでした。入力がオブザーバブルの値で初期化されていませんでした。更新されたバインディングを作成し、これに次を追加しました。

$(element).datepicker('update', dataSource());

それはトリックを行うようです。

利用可能な最新の日付ピッカー、Bootstrap、jQuery、および Knockout を使用する更新されたフィドルは次のとおりです: http://jsfiddle.net/krainey/nxhqerxg/

アップデート:

ユーザーがテキスト フィールドの値を手動で編集するときに、日付ピッカーがオブザーバブルをうまく処理できないという問題が発生しました。ツールはすぐに日付を解析し、結果を入力フィールドに挿入します。

たとえば、ユーザーが 10/07/2014 を編集しようとして、バックスペースまたは削除を使用して数値を削除した場合 (10/0/2014)、結果の値はすぐに解析され、テキスト入力に挿入されます。値が一瞬 2014 年 10 月 0 日だった場合、ピッカーはカレンダーを 2014 年 9 月 30 日にシフトし、その値をテキスト フィールドに挿入します。月を編集しようとして、値が一瞬 2014 年 1 月 7 日だった場合、ピッカーは 2014 年 1 月 7 日にシフトし、その値をテキスト フィールドに挿入します。

このフィドルでその動作を確認できます。

http://jsfiddle.net/krainey/nxhqerxg/10/

フォーカスを検出する特別なハンドラーを使用してバインドを更新し、手動編集を正しく処理できるように 1 回限りのぼかしイベントをバインドする必要がありました。

$(element).on("changeDate", function (ev) {
    var observable = valueAccessor();
    if ($(element).is(':focus')) {
        // Don't update while the user is in the field...
        // Instead, handle focus loss
        $(element).one('blur', function(ev){
            var dateVal = $(element).datepicker("getDate");
            observable(dateVal);
        });
    }
    else {
        observable(ev.date);
    }
});

元の回答で参照されているフィドルは、これを反映するように更新されました。

http://jsfiddle.net/krainey/nxhqerxg/

于 2014-09-24T16:35:53.010 に答える
2

ここに私が終わったものがあります

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

    var options = {
        autoclose: true,
        format: 'yyyy-mm-dd',
    }

    //var options = allBindingsAccessor().datepickerOptions || {};
    $(element).datepicker(options);

    //when a user changes the date, update the view model
    ko.utils.registerEventHandler(element, "changeDate", function (event) {
        var value = valueAccessor();

        if (ko.isObservable(value)) {
            var myDate = event.date;
            var month = myDate.getMonth() + 1;
            var monthText = month;

            if (month < 10)
                monthText = "0" + month;

            var day1 = parseInt(myDate.getDate());
            var dayText = day1;

            if (day1 < 10)
                dayText = '0' + day1;

            value(myDate.getFullYear() + '-' + monthText + '-' + dayText);
        }
    });
},
update: function (element, valueAccessor) {

    var widget = $(element).data("datepicker");
    //when the view model is updated, update the widget
    if (widget) {
        widget.date = ko.utils.unwrapObservable(valueAccessor());
        widget.setValue(widget.date);
    }
}};
于 2014-06-16T09:58:38.017 に答える