Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding DateTime to knockout view model with default JavaScriptSerializer

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

like image 938
CraftyFella Avatar asked Jan 25 '11 20:01

CraftyFella


2 Answers

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.

like image 161
Sergei Golos Avatar answered Nov 09 '22 17:11

Sergei Golos


Not an elegant solution, but it works:

data-bind="value: eval('new ' + Modified.slice(1,-1)), uniqueName: true"

Eval might be a security issue here depending on the context.

like image 42
Don Smith Avatar answered Nov 09 '22 17:11

Don Smith