Knockout.js 3.3.0 options binding for jQuery mobile 1.4 select - jquery-mobile

I'm using knockout.js 3.3.0 with jQuery mobile 1.4.
The problem using knockout.js together with jQuery mobile is that the programmatically changes to the underlying viewmodel are not always reflected to the graphical user interface, due to the JQM refactoring of the html elements, or widgets. So, for example, the JQM selectmenu is synchronized from the user interface to the viewmodel, but not in the other way.
I'm trying to stick together the 3.3.0 KO 'options' binding with a custombinding to the current JQM actual version.
There are already two possible solutions for the 'refresh' problem already proposed at SO for 2.x versions of KO: jqmSelect and jqmValue, as custombindings.
I try this suggestions for a more recent KO+JQM combination, putting together all the answers/comments found at SO regarding this topic.
This is the js that i'm using to test:
$(document).ready(function () {
var jsonResultData = [{
"id": 6,
"name": "First item",
"pattern": "Cheetah"
}, {
"id": 2,
"name": "Second item",
"pattern": "Viper"
}, {
"id": 1,
"name": "Third item",
"pattern": "Scorpion"
}];
ko.applyBindings(new AdminViewModel(jsonResultData));
});
function Match(data) {
this.id = ko.observable(data.id);
this.pattern = ko.observable(data.pattern);
this.name = ko.observable(data.name);
}
function AdminViewModel(allData) {
var self = this;
self.matches = ko.observableArray([]);
self.matchesFromDb = $.map(allData, function (item) {
return new Match(item);
});
self.matches = self.matchesFromDb;
self.selectedMatchId = ko.observable(self.matches[0].id());
self.selectedMatch = ko.observable(self.matches[0]);
self.setSelectedMatchId = function (match) {
if (match.id() != self.selectedMatchId()) {
self.selectedMatchId(match.id());
self.selectedMatch(match);
}
};
self.patternValues = ko.observableArray(["Shark", "Viper", "Chameleon", "Cheetah", "Scorpion"]);
}
I made a fiddle to test the jqmValue custom binding, which is one of the latest soultions found at SO, but but i'm not able to get it to work:
ko.bindingHandlers.jqmValue = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.init !== 'undefined') {
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var instance;
if (typeof ko.bindingHandlers.value.update !== 'undefined') {
ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
instance = $.data(element, 'mobile-selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
(the original code for AdminViewModel as reference for KO 2.x thanks to pablo is working with the suggested change to invert value/options in the markup thanks to JohnEarles at google groups)
Here is the fiddle with actual KO and JQM versions where i try to include the best of all suggestions found regarding this topic:
http://jsfiddle.net/nHNzL/42/
but i'm still streching my hairs without success. Why in my test fiddle the changes to the viewmodel are not reflected to the JQM selectmenu? What is my error?
UPDATE: two-page fiddle to test also initialization: http://jsfiddle.net/nHNzL/50/
FINAL VERSION:
I made 2 small fixes and 1 change:
1) isInstance shall be checked every time
2) removed the if (currentValue == value)
3) inverted the disabled attribute
Moreover: i tested this custombinding in a ko foreach-loop, each select element needs to be child of an own container div.
ko.bindingHandlers.jqmSelectMenu = {
init: function (element, valueAccessor, allBindings) {
var options = ko.toJS(valueAccessor()),
valueObservable = allBindings.get("value"), valueSubscription,
optionsObservable = allBindings.get("options"), optionsSubscription;
var refresh = function () {
var $el = $(element);
var isInstance = !!$.data(element, 'mobile-selectmenu');
if (isInstance) {
$el.selectmenu('refresh', true);
} else {
/* instantiate the widget unless jqm has already done so */
$(element).selectmenu(options);
}
};
refresh();
/* hook up to the observables that make up the underlying <select> */
if (ko.isSubscribable(valueObservable)) {
valueSubscription = valueObservable.subscribe(refresh);
}
if (ko.isSubscribable(optionsObservable)) {
optionsSubscription = optionsObservable.subscribe(refresh);
}
/* properly dispose of widgets & subscriptions when element is removed */
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).selectmenu("destroy");
if (valueSubscription) valueSubscription.dispose();
if (optionsSubscription) optionsSubscription.dispose();
});
},
update: function (element, valueAccessor, allBindings) {
var options = ko.toJS(valueAccessor()),
$el = $(element);
/* update any widget options if necessary */
ko.utils.objectForEach(options, function (key, value) {
if (key === "enabled") {
$el.selectmenu(value ? "enable" : "disable");
} else {
$el.selectmenu("option", key, value);
}
});
}
};

In fact you are mixing two separate things.
There is the underlying <select> element. It holds the available options as well as the selected one.
Then there is the jQuery Mobile SelectMenu widget. It is concerned with the UX part. A look at the API options it provides reveals that it really has not a lot to do with the underlying select box, mostly using it for self-initialization.
Of course the widget communicates a value change to the underlying select box, but when you change the value programmatically you must communicate that to the widget yourself, by calling refresh on it. So even without knockout this is not a two-way communication.
We do have set of knockout built-in bindings that work very well with select boxes, but what we don't have is a binding that communicates changes in those values to the widget. What we also don't have is a way of initializing/updating any of the widget's API options.
So instead of re-inventing the value binding we need one that deals with the widget itself and otherwise simply complements the existing bindings:
ko.bindingHandlers.jqmSelectMenu = {
init: function (element, valueAccessor, allBindings) {
var options = ko.toJS(valueAccessor()),
valueObservable = allBindings.get("value"), valueSubscription,
optionsObservable = allBindings.get("options"), optionsSubscription,
isInstance = !!$.data(element, 'mobile-selectmenu'),
refresh = function () { $(element).selectmenu('refresh', true); };
// instantiate the widget unless jqm has already done so
if (!isInstance) $(element).selectmenu(options);
refresh();
// hook up to the observables that make up the underlying <select>
if (ko.isSubscribable(valueObservable)) {
valueSubscription = valueObservable.subscribe(refresh);
}
if (ko.isSubscribable(optionsObservable)) {
optionsSubscription = optionsObservable.subscribe(refresh);
}
// properly dispose of widgets & subscriptions when element is removed
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).selectmenu("destroy");
if (valueSubscription) valueSubscription.dispose();
if (optionsSubscription) optionsSubscription.dispose();
});
},
update: function (element, valueAccessor, allBindings) {
var options = ko.toJS(valueAccessor()),
$elem = $(element);
// update any widget options if necessary
ko.utils.objectForEach(options, function (key, value) {
var currentValue = $elem.selectmenu("option", key);
if (currentValue !== value) {
if (key === "disabled") {
$elem.selectmenu(value ? "disable" : "enable");
} else {
$elem.selectmenu("option", key, value);
}
}
});
}
};
I have written this in the spirit of the knockout-jQueryUI. I recommend taking a look at that library.
Here's an updated fiddle, too. http://jsfiddle.net/nHNzL/46/

Related

Knockout Custom Binding and Running a ViewModel Function

I found a custom binding that makes an observable update in an editable div.
I'm not able to run a function when an event occurs with it.
Does anyone know what I can do to my custom binding "editableText" run a function in my ViewModel?
I would like the function "nameChange" to run when text is changed.
HTML:
<div contenteditable="true" data-bind="event: { change: nameChange }, editableText: firstName"></div>
Javascript:
//Editable Text Custom Binding
ko.bindingHandlers.editableText = {
init: function (element, valueAccessor) {
$(element).on('blur', function () {
var observable = valueAccessor();
observable($(this).text());
});
},
update: function (element, valueAccessor, allBindingsAccessor, data) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).text(value);
}
};
//Knockout ViewModel
function viewModel(){
var self = this;
self.firstName = ko.observable();
self.status = ko.observable();
self.nameChange = function(){
console.log("Name has been updated");
ko.mapping.fromJS("Name has been updated", {}, self.status)
}
self.loadName = function(){
ko.mapping.fromJS("hey", {}, self.firstName)
}
}
var vm = new viewModel();
ko.applyBindings(vm);
vm.loadName();
JSFIDDLE:
http://jsfiddle.net/madscientist1882/urLd2/
How about subscribing to changes on the observable? (Look at explicitly subscribing to observables)
self.firstNameSubscription = self.firstName.subscribe(function (newValue){
//do something
});
If you do this you need to dispose of the subscription when your view model goes down
self.firstNameSubscription.dispose();
If you want the observable to be updated every time a key is entered have a look here
My personal opinon is that using the variable name 'self' is probably a bad idea...

using JQueryUI DateTimePicker with Knockout

In Continuation of
knockout js bind with datetimepicker gives an exception
I am now able to use the datetimepicker with knockout but I am unable to use the time picker option of the same tool the code I have tried is embedded into the following jsfiddle but is throwing an error
<code>
http://jsfiddle.net/saqibshakil/scdET/
</code>
check console after edit
Looks like calling getDate on timepicker does not return an actual Date.
It appears that you can call it using datetimepicker successfully. So, your binding would look like:
ko.bindingHandlers.timepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize timepicker with some optional options
var options = allBindingsAccessor().timepickerOptions || {};
$(element).timepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).datetimepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).timepicker("destroy");
});
},
//update the control when the view model changes
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datetimepicker("getDate");
if (value - current !== 0) {
$(element).datetimepicker("setDate", value);
}
}
};
Updated sample: http://jsfiddle.net/rniemeyer/L3BNw/

knockout js bootstrap datepicker

i know this question is asked lot of times before... but i have tried all the solutions and none of them are working.... hence asking again...
how do i bind the json date to knockout element... below is the code i have...
#Html.Bootstrap().ControlGroup().TextBoxFor(x => x.DateOfBirth).HtmlAttributes(new { data_bind = "kodate: DateOfBirth, datepickerOptions : new Date()", #class = "datepicker" })
$(function () {
$('.datepicker').datepicker({
autoclose: true
});
});
<input data-bind="kodate: startdate" class="datepicker"/>
the kodate is defined as below
ko.bindingHandlers.kodate = {
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);
}
});
ko.utils.registerEventHandler(element, "change", function () {
var value = valueAccessor();
if (ko.isObservable(value)) {
value(new Date(element.value));
}
});
},
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) {
return;
}
if (_.isString(widget.date)) {
widget.date = new Date(parseInt(widget.date.replace(/\/Date\((.*?)\)\//gi, "$1")));
//widget.date = new Date(widget.date);
}
widget.setValue();
}
},
update_old: 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")));
}
$(element).datepicker("setValue", value);
}
};
now the date is being displayed correctly... but when i post the date... it is posted in json format and the model binder is not able to convert the json date (/Date(1339230900000)/) to the actual date and hence the date remains null on server side...
how do make sure that the model binder converts the json date /Date(1339230900000)/ to the server side DateTime or how to post the date in different format so that model binder is able to recognize the date??
interesting thing is if i change the date, then its posted in ISO format, but if i don't change the date then its posted in json format... so may be something wrong with the init code...
i am using bootstrap-datepicker: https://github.com/eternicode/bootstrap-datepicker
any help is greatly appreciated...
The easiest way to do this is using a client-side library such as Moment.js to format your date properly while maintaining the two-way data-binding offered by Knockout. A simple way to get started is using a lightweight plug-in like shown here - http://makingsense.github.io/moment-datepicker/
You are not required to use that plug-in though, you just need to write your own custom binding handler to handle getting and setting the date. An example of this that I have used in the past -
Register a binding handler to format the date to bind to -
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"));
});
//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());
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
var current = $(element).datepicker("getDate");
if (value - current !== 0) {
$(element).datepicker("setDate", value);
}
}
};
And then the mark-up -
<div class="span4">
<label>Start Date : </label><input data-bind="datepicker: startDate, datepickerOptions: { maxDate: new Date() }" />
</div>
Note: This answer was derived from an aggregation of other answers.

Knockout and jQuery Mobile: Binding data to select lists

I'm using both Knockout (version 2.0) and jQuery Mobile (version 1.0.1) in the same project. The problem is with binding data to select lists. jQuery Mobile presents select lists in a way where the seemingly selected value and the actual list are separate elements. This is fixed by executing
$(element).selectmenu('refresh', true);
after changing either the list or the selected value. Based on my experience, this is a dangerous situation as developers often forget to refresh select list.
To ease this, I wrote my own Knockout binding handler. The values are bound to the select list with following code:
<select name="selection" data-bind="jqmOptions: values, optionsValue: 'id', optionsText: 'name', value: selectedValue">
</select>
The implementation of jqmOptions:
ko.bindingHandlers.jqmOptions = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.options.init !== 'undefined') {
ko.bindingHandlers.options.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.options.update !== 'undefined') {
ko.bindingHandlers.options.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
var instance = $.data(element, 'selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
This uses the native options binding but in addition to that, it automatically refreshes select lists after changing the list values. There is a problem with this however when I'm changing the selected value. If I first set the list values, my jqmOptions refreshes the select list but at that point, the selected value is not yet set. I end up with a select list, which has all the correct values and internally the right option is selected, but jQuery Mobile still displays the default value as selected.
this.values(someArrayOfValues);
this.selectedValue(oneOfTheArrayValues);
Knockout doesn't allow me to first set the selected value and then setting the list values, because in this case there are no allowed values when I'm setting the selected value. Thus the selected value is always undefined.
Is there a way to write a Knockout custom binding which would refresh the select list element in both cases: when changing the list value and when changing the selected value?
Currently I solve this situation with following code:
this.values(someArrayOfValues);
this.selectedValue(oneOfTheArrayValues);
this.values(someArrayOfValues);
This is not very elegant solution however and I would like to solve it better.
I ended up solving myself. I wrote my own jqmValue binding:
ko.bindingHandlers.jqmValue = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.init !== 'undefined') {
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.update !== 'undefined') {
ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
var instance = $.data(element, 'selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
The select list code is then changed to following:
I already tried implementing this yesterday before asking the question, but apparently I wrote it poorly then because it didn't work. However, now with a fresh pair of eyes I managed to implement it correctly so hopefully this answer solves the problem for other Knockout and jQuery Mobile users too.
For my personal experience (with jquerymobile 1.1.0 and knockoutjs 2.1.0), I've only used jqmoptions (as seen in the first post) binding to have a valid knockout binding to a select. To make 'value' binding works with select, simply declare it as first in the binding
<select name="myname" id="myid" data-bind="value: myvalue, jqmoptions: myvalues, optionsValue: 'id', optionsText: 'desc'"></select>
Looks that the order is mandatory: http://goo.gl/nVbHc
Just for clarity, the best solution now for KO 3.x would be:
ko.bindingHandlers.jqmValue = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.init !== 'undefined') {
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var instance;
if (typeof ko.bindingHandlers.value.update !== 'undefined') {
ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
instance = $.data(element, 'mobile-selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
And the matching HTML use:
<select data-bind="options: optionsList, optionsValue: 'Id', optionsText: 'Title', jqmValue: knockoutobservable"></select>
using both Knockout 3.3 + jQuery Mobile 1.4.5 and also had the same problem
when i had multiple selections which binding one value
<select id="myselect1" data-bind="options: modelsA-Z, value: myModel"></select>
<select id="myselect2" data-bind="options: modelsFamous, value: myModel"></select>
1st/2nd select not shown the init value and 2nd not updated after...
I finally use below binding: (replace above value:myModel -> jqmValue: myModel)
ko.bindingHandlers.jqmValue = {
init: function (element, valueAccessor) {
var result = ko.bindingHandlers.value.init.apply(this, arguments);
try {
$(element).selectmenu("refresh");
} catch (x) {}
return result;
},
update: function (element, valueAccessor) {
ko.bindingHandlers.value.update.apply(this, arguments);
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
try {
$(element).selectmenu("refresh");
} catch (x) {}
}
};

knockoutjs databind with jquery-ui datepicker

I'm using a jQuery UI datepicker. The HTML input field behind it is currently hooked up to KnockoutJS as a dependentObservable, but when its value is set in the viewmodel, the datepicker loses its format.
How should I do this and not lose the format? I would like the viewModel not to know that it is a jQuery datepicker.
You could write a custom binding that sets the date in the field using the datepicker APIs and also sets the value of your observable by reading the date properly.
The custom binding might look like:
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);
}
}
};
You would use it like:
<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />
The datepickeroptions would be optional and could include anything that you want to pass into the datepicker() call.
Also, this assumes that you are using an observable for the date. The binding has to do a little more work if you want to do a one-way binding with a non-observable, but that is unlikely.
Sample here: http://jsfiddle.net/rniemeyer/NAgNV/
I had to make a slight edit to RP Niemeyer's code to work in my code using the dateFormat option, replacing
$(element).datepicker("getDate")
With
$(element).val()
So the formatted version of the date was passed around correctly under the hood.
I've been using RP Niemeyer's code marked as the answer above, but since I've been using it I've made a few small changes to it. I thought I would post here. Maybe it will help others. It's pretty much the same, the only difference is that if the element has a value when the page loads then it will retain its value. Also, I made $elem a variable so that there will be less processing of $(element) that jQuery will have to do.
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);
}
}
};
Here is what worked for my particular set of circumstances. I'm running a new enough version of MVC, that the default datetime serializer renders at ISO 8601 (see On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web API). My bindings do not write directly to the date picker, but instead to an input tag's "value" attribute.
Also, of note, I'm using 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"));
});
}
}
Binding looks like this:
<input class="date" type="text" data-bind="dateValue: SomeViewModelDate" />
And the JavaScript code to turn on the datepicker:
$(document).ready(function () {
$('.date').datepicker({ dateFormat: "mm/dd/yy" });
});
The datepicker samples above change the format of the date in the viewmodel from WCF format to the JavaScript date format when the user selects a new date from the datepicker control.
In my case, I was passing the date back to a WCF service, and it would not accept a deserialized JavaScript date, it needed the date in the WCF format. I modified the above script so that it stores the date in the viewmodel in WCF format so that it can be sent back to the server in that format.
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);
}
}
};
One solution is to format the date yourself inside the dependentObservable function. So you must be returning something like return viewModel.someOtherObservable() in the function. Format the return value.
If you include your code, I can explain more.
Formatting the date (to mm/dd/yyyy) inside the dependentObservable is exactly what I was wondering how to do. I'll post a little of my code if you can help, Peter Mortensen and/or nEEBz.
<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>
in ViewModel - technologydetail.js:
var technology = ko.observable();
in Activate:
return dataContext.getTechnologyById(currentTechnologyId, technology);
This displays a date that looks like this in the textbox: Wed Jan 29 19:00:00 EST 2014 but
I want it to just show: 01/29/2014. I am using this datepicker option - dateFormat: "mm/dd/yy" but it has no effect on the initial value displayed.
I was able to format it using moment and it works nicely for displaying the current database value, but it seems to be breaking the binding back to the observable because it will no longer update on a SAVE.
<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: moment(END_OF_LIFE_DATE()).format('MM/DD/YYYY')" />

Resources