2011-06-18 16 views
35

私はjQuery UI datepickerを使用しています。その背後にあるHTML入力フィールドは、現在、dependentObservableとしてKnockoutJSに接続されていますが、その値がviewmodelで設定されている場合、datepickerのフォーマットは失われます。jquery-ui datepickerでknockoutjsデータバインド

フォーマットを失うことなく、どうすればよいですか?私はviewModelがjQuery datepickerであることを知らないことを望みます。

答えて

73

datepicker APIを使用してフィールドに日付を設定するカスタムバインディングを作成し、日付を正しく読み取ることによってobservableの値を設定することもできます。

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

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

datepickeroptionsはオプションとなり、あなたがdatepicker()呼び出しに渡したいものを含めることができます:あなたが好きな、それを使用することになり

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

また、これは、あなたが日付の観測値を使用していることを前提としています。あなたが観測不可能な一方向バインディングをしたいのであれば、バインディングはもう少し作業をしなければなりませんが、それは起こりそうもありません。ここ

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

+0

datepickerと "with:submodelObject"スタイルバインディングの連携を強化するには、このカスタムバインディングをどのように変更する必要がありますか?私の使用では、表示されたに接続できるまで、datepickerのdivが表示されるように表示されました。 "template:{afterRender:jqueryDecoratingMethod、data:submodelObject}"を使用するとうまくいきました。 –

+0

@TetsujinnoOniあなたは問題を抱えているサンプルを持っていますか?見ていただければ幸いです。 –

+0

Ryan - オファーに感謝します。私はフィドルで再現することができません。私は(ページ上の他の醜さのために)私がテーマjqueryuiを忘れてしまった、あるいは私のCSSで同じように醜いことが起こっていると思われます。私はそれを特定の要素の組み合わせに絞り込むことができますリンクやフィドル –

0

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

コードを含めると、もっと説明できます。

6

私はそう

$(element).val() 

$(element).datepicker("getDate") 

を交換し、DATEFORMATオプションを使用して私のコードで動作するようにRPニーマイヤーのコードに若干の編集をしなければなりませんでした日付の書式設定されたバージョンは、フードの下で正しく渡されました。

6

私は上記の答えとしてマークされたRPニーマイヤーのコードを使用してきたが、私はそれを使用してきたので、私はそれにいくつかの小さな変更を加えました。私はここに投稿すると思った。多分それは他人を助けるでしょう。殆ど同じですが、唯一の違いは、要素がページの読み込み時に値を持つ場合、その値が保持されることです。また、$elemを変数にして、jQueryが行う必要がある$(element)の処理が少なくなるようにしました。ユーザが日付ピッカーコントロールから新しい日付を選択したとき

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

私はそれを掘り下げませんでしたが、日付ピッカーの初期値はバインドされたobservableの値に設定されていませんでした。 – dhochee

1

日付ピッカーサンプルは、上記のJavaScriptの日付フォーマットにWCFフォーマットからのviewmodelに日付の書式を変更します。私の場合は

、私はWCFサービスに戻って日付を渡した、そしてそれは、デシリアライズJavaScriptの日付を受け入れないだろう、それはWCF形式で日付を必要としていました。それはその形式でサーバに送り返すことができるように、それはWCF形式でのviewmodelで日付を格納するように私は、上記のスクリプトを変更しました。

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

ここは、私の特定の状況に適したものです。私は、デフォルトのdatetimeシリアライザがISO 8601(On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web APIを参照)でレンダリングするMVCの十分な新しいバージョンを実行しています。私のバインディングは、日付ピッカーに直接書き込むのではなく、入力タグの「value」属性に書き込むことができます。

また、注目すべき、私はこのような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" }); 
}); 
+0

バインディングを適用する前にコードをどこに置くべきですか?今度はエラーが発生します:Uncaught TypeError:バインディングを処理できません "メッセージ:バインディングを処理できません" dateValue:function(){return startDate} "メッセージ:プロパティを読み取れません 'toString 'の –

0

dependentObservable内の日付を(mm/dd/yyyyに)フォーマットすることは、まさに私がどのように思っていたかですする。もしあなたが助けてくれれば、私のコードを少し投稿します、Peter Mortensenおよび/またはnEEBz。 ViewModelにで

<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> 

- technologydetail.js:アクティブで

var technology = ko.observable(); 

return dataContext.getTechnologyById(currentTechnologyId, technology); 

これは、テキストボックスに次のようになります日付が表示されます:1月29日水曜日19時: 00 EST 2014だが、 私はちょうどそれを表示したい: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')" /> 
関連する問題