Binding DateTime to knockout view model with default JavaScriptSerializer

CraftyFella picture CraftyFella · Jan 25, 2011 · Viewed 19.5k times · Source

I've just started using knockout and I'm running into trouble with DateTime Serialization and Deserialization using the JavaScriptSerializer.

I've updated the gifts model in Steves koListEditor example from his blog to include a Modified DateTime field:

public class GiftModel
{
    public string Title { get; set; }
    public double Price { get; set; }
    public DateTime Modified { get; set; }
}

Then I updated the Index.aspx to include the new field:

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <h1>Gift list editor</h1>

    <p>You have asked for <span data-bind="text: gifts().length">&nbsp;</span> gift(s)</p>

    <form class="giftListEditor">
        <table> 
            <tbody data-bind="template: { name: 'giftRowTemplate', foreach: gifts }"></tbody> 
        </table>

        <button data-bind="click: addGift">Add Gift</button>
        <button data-bind="enable: gifts().length > 0" type="submit">Submit</button>
    </form>

    <script type="text/html" id="giftRowTemplate"> 
        <tr> 
            <td>Gift name: <input class="required" data-bind="value: Title, uniqueName: true"/></td> 
            <td>Price: \$ <input class="required number" data-bind="value: Price, uniqueName: true"/></td> 
            <td>Modified:  <input class="required date" data-bind="value: Modified, uniqueName: true"/></td> 
            <td><a href="#" data-bind="click: function() { viewModel.removeGift($data) }">Delete</a></td> 
        </tr>
    </script>

    <script type="text/javascript">
        var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
        var viewModel = { 
            gifts : ko.observableArray(initialData), 

            addGift: function () { 
                this.gifts.push({ Title: "", Price: "", Modified:"" }); 
            },

            removeGift: function (gift) { 
                this.gifts.remove(gift); 
            },

            save: function() { 
                ko.utils.postJson(location.href, { gifts: this.gifts }); 
            } 
        }; 

        ko.applyBindings(document.body, viewModel);
        $("form").validate({ submitHandler: function() { viewModel.save() } });
    </script> </asp:Content>

However when the JavaScriptSerializer serializes the Model

var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;

the Modified Date is coming out like this:

DateTime problem

Also when using UK Dates I.e. 25/01/2011 the JavaScriptSerializer.Deserialize throws the following exception:

25/01/2011 is not a valid value for DateTime.

Although i'm having 2 problems here the main question is has anyone successfully used knockout from MVC 2 and got the JavaScriptSerializer working with DateTimes? I realise I could write my own JavaScriptSerializer but I was hoping there was a ready made solution out there :)

Here's the code for the updated version of Steve Sanderson's koListEditor:

Code on my skydrive

Thanks

Dave

Answer

Sergei Golos picture Sergei Golos · Feb 23, 2011

Well there are two options. You could do the simple fix by having a designated view model object which stores the preformated date time values as a string. This is generally what i do. I can then tryparse for the date value for validation.

The other option would be to implement a custom data binding. You can look at doing that here. This would be the more elegant approach. The nice thing about this apporach, you can then create you UI generation code on binding allowing you to add date picker to the ui in the process.