Reputation: 11975
I was trying to hack my way around with the metro.js datepicker and knockout. So far my datepicker binding code looks like:
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;
};
}
}
Issue is that when I issue a model update on the date
property its bound to the datepicker doesn't update. I mean, it does it the very first time, but post that, it fails to update the textbox; calendar shows okay however. Ultimately I need to change the logic in the applyDate
function...
JSBin: http://jsbin.com/rupaqolexa/1/edit?html,js,output
Update: Another issue just cropped up...it doesn't work in IE 10+. The date appears as NaN
in the UI...
Update: Steps for reproduction
Upvotes: 0
Views: 155
Reputation: 39015
In the update
part of your custom binding you need to make all the changes to the bound elements, which include the calendar widget, and the related input
element.
I've modified the code to do so, so that it now works.
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>
However there is still a little hiccup: the datepiceker's calendar setdate
adss new selected date, instead of replacing selected ones. Please, see the API docs to solve this yourself.
Upvotes: 1