0

私は、metro.js の日付ピッカーとノックアウトを使ってハッキングしようとしていました。これまでのところ、私の日付ピッカー バインディング コードは次のようになります。

ko.bindingHandlers.datepicker = {
  init: function(el, va, ba, model, ctx) {
    var prop = va();
    $(el).datepicker({
      onSelect: function(txt, date) {
        prop(date);
      }
    });
  },
  update: function(el, va, ba, model, ctx) {
    var prop = va();
    var date = ko.unwrap(prop);

    if(date) {
      applyDate(date);
    }

    function applyDate(dt) {
      var j = $(el);
      var dp = j.data('datepicker');
      var inp = j.find('input');
      var fmt = dp.options.format;
      var sDate = format(fmt, dt);
      // dp._calendar.calendar.dayClick(sDate, dt);
      // inp.value = sDate;
      dp._calendar.calendar('setDate', sDate);
      j.find('input').val(dp._calendar.calendar('getDate')).trigger('change', sDate);
    }

    function format(fmt, dt) {
      fmt = fmt.replace('yyyy', dt.getFullYear());
      fmt = fmt.replace('mm', pad(dt.getMonth() + 1));
      fmt = fmt.replace('dd', pad(dt.getDate()));
      return fmt;
    }

    function pad(n) {
      return parseInt(n) < 10 ? '0' + n: '' + n;
    };
  }
}

問題は、dateプロパティでモデルの更新を発行すると、datepicker にバインドされたものが更新されないことです。つまり、それは初めてのことですが、それを投稿すると、テキストボックスの更新に失敗します。ただし、カレンダーは正常に表示されます。最終的には、関数のロジックを変更する必要がありapplyDateます...

JSBin: http://jsbin.com/rupaqolexa/1/edit?html,js,output

更新: 別の問題が発生しました... IE 10 以降では機能しません。日付NaNはUIのように表示されます...

更新: 再現手順

  1. 日付 2 番目のテキスト ボックス: 2013/05/13 を入力し、[変更] ボタンをクリックします。日付ピッカーのテキストボックスで観察日が更新されます。これは期待どおりに機能します。(IE を除く)。
  2. テキストボックスに別の日付を入力し、変更ボタンをクリックします。datepicker テキストボックスで日付が更新されていないことを確認します。ここで、datepicker テキストボックスが最新の値で更新されることが期待されます。
4

1 に答える 1

1

カスタム バインドのupdate一部では、バインドされた要素 (カレンダー ウィジェットと関連要素を含む) にすべての変更を加える必要がありますinput

そのようにコードを修正したので、今は動作します。

function ViewModel(date) {
  var model = this;
  model.date = ko.observable(date);
  model.set = function() {
    var val = $('#somedate').val();
    var dt = new Date(val);
    model.date(dt);
  };
}

ko.bindingHandlers.datepicker = {
  init: function(el, va, ba, model, ctx) {
    var prop = va();
    $(el).datepicker({
      onSelect: function(txt, date) {
        prop(date);
      }
    });
  },
  update: function(el, va, ba, model, ctx) {
    var newDate = ko.unwrap(va());

    if(newDate) {
      var $el = $(el);
      var datePicker = $el.data('datepicker');
      var $input = $el.find('input');
      var formattedDate = format(datePicker.options.format, newDate);
      datePicker._calendar.calendar('setDate', formattedDate);
      $input.val(formattedDate);
      //$input.val(dp._calendar.calendar('getDate'))
      //  .trigger('change', sDate);
    }

    function format(fmt, dt) {
      fmt = fmt.replace('yyyy', dt.getFullYear());
      fmt = fmt.replace('mm', pad(dt.getMonth() + 1));
      fmt = fmt.replace('dd', pad(dt.getDate()));
      return fmt;
    }

    function pad(n) {
      return parseInt(n) < 10 ? '0' + n: '' + n;
    }
  }
};

var m = new ViewModel();

$(function(){
  ko.applyBindings(m);
});
<link href="//metroui.org.ua/css/metro.css" rel="stylesheet">
<link href="//metroui.org.ua/css/metro-icons.css" rel="stylesheet">
<link href="//metroui.org.ua/css/metro-responsive.css" rel="stylesheet">
<link href="http://metroui.org.ua/css/metro-schemes.css" rel="stylesheet">

<script src="http://metroui.org.ua/js/jquery-2.1.3.min.js"></script>
<script src="http://metroui.org.ua/js/metro.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-debug.js"></script>

<div>
  <div class="input-control text" data-bind="datepicker: date">
    <input type="text">
    <button class="button"><span class="mif-calendar"></span></button>
  </div>
</div>
<div>
  <label>Date</label>
  <div class="input-control text">
    <input type="text" id="somedate"/>
  </div>
  <input type="button" class="button" value="Change" data-bind="click: set"/>
</div>

<div>
  <code data-bind="text: date"></code>
</div>

ただし、まだ少し問題があります。datepiceker のカレンダーsetdate広告は、選択した日付を置き換えるのではなく、新しく選択した日付を表示します。これを自分で解決するには、API ドキュメントを参照してください。

于 2015-11-19T10:11:17.377 に答える