Reputation: 3026
I'm using knockout to bind my view model to my view. Multiple properties in my view model are nullable, such as DateTime?
s. Here's an example:
public class ViewModel
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime? CreationDate { get; set;}
}
As you can see, the property CreationDate
is a nullable DateTime
.
I'm binding the property with a custom datepicker binder:
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
try {
var jsonDate = ko.utils.unwrapObservable(valueAccessor());
var value = parseJsonDateString(jsonDate);
var strDate = value.getMonth() + 1 + "/"
+ value.getDate() + "/"
+ value.getFullYear();
element.setAttribute('value', strDate);
}
catch (exc) {
}
$(element).change(function () {
var value = valueAccessor();
value(element.getAttribute('value'));
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var val = valueAccessor();
val(element.getAttribute('value'));
}
};
var jsonDateRE = /^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/;
var parseJsonDateString = function (value) {
var arr = value && jsonDateRE.exec(value);
if (arr) {
return new Date(parseInt(arr[1]));
}
return value;
};
This enables me to bind my property in the view like so:
<input type="text" data-bind="datepicker: CreationDate" />
Problem
Here's the problem. Sometimes this property is already null when it enters the view. A JSON example could look like this:
{
"Id": 2004,
"Name": "Test",
"CreationDate": null
}
If this is the case, and I change this value to some random value from the datepicker, and send an ajax POST to my controller, I can see that models CreationDate
still is equal to null
.
So if the DateTime
is null as the model enters the view, how do I populate the models property?
Upvotes: 0
Views: 990
Reputation: 3026
Found the solution on my own
I managed to solve my issue by simply changing my binding to the following:
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();
var value = $(element).val();
// if the input field is empty, the value is falsy and therefore the observable should be = null
if(!value){
observable(null);
} else {
var date = new Date(value);
observable(date);
}
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
},
//update the control when the view model changes
update: function (element, valueAccessor) {
var value = ko.unwrap(valueAccessor());
//if the value received is null, we should display nothing in the input field
if (value === null) {
$(element).val(null);
} else {
//we need to manipulate the data to show something user friendly to the user
var date = parseJsonDateString(value);
var strDate = date.getMonth() + 1 + "/"
+ date.getDate() + "/"
+ date.getFullYear();
$(element).val(strDate);
}
}
};
So basically if the value I'm getting in the update
function, simply set $(element).val(null)
. This way, nullable properties are handled correctly.
Upvotes: 1