Create a basic Grid using KnockoutJS Mapping plugin and MVC 3

I have searched high and low and tried various patterns but it seems I cannot get it to work right. The one time I got it to work there was so much code I figured there had to be an easier way and now its completely broken. my goal... to understand the basics of how to use KO Mapping and MVC to have this grid load.. and possibly use a form to update it. I cannot find any examples that are working for my situation. Here is what I am down too now.

Here is my Action:

public JsonResult List()
    {
        var result = new JsonResult();
        result.Data = _service.GetWeightStats();

        return Json(result, JsonRequestBehavior.AllowGet);
    }

Here is my Class:

public class WeightStat
{
    public int Id { get; set; }
    [Required]
    public double Weight { get; set; }
    public double? Neck { get; set; }
    public double? Chest { get; set; }
    public double? Bicept { get; set; }
    public double? Waist { get; set; }
    public double? Hip { get; set; }
    public double? Thigh { get; set; }
    public double? Calf { get; set; }
    [Required]
    public DateTime Date { get; set; }
    [Required]
    public string TimeOfDay { get; set; }
    [Required]
    public string DietBehavior { get; set; }

}

Here is my template line:

<tbody data-bind='template: {name: "statRowTemplate", foreach: data.Data }'></tbody>

Here is my template:

<script id="statRowTemplate" type="text/html">
    <tr data-bind="attr: { id: Id }">
            <td><span data-bind="text: Date"></span></td>
            <td><span data-bind="text: TimeOfDay"></span></td>
            <td><span data-bind="text: DietBehavior"></span></td>
            <td><span data-bind="text: Weight"></span></td>
            <td><span data-bind="text: Neck"></span></td>
            <td><span data-bind="text: Chest"></span></td>
            <td><span data-bind="text: Bicept"></span></td>
            <td><span data-bind="text: Waist"></span></td>
            <td><span data-bind="text: Hip"></span></td>
            <td><span data-bind="text: Thigh"></span></td>
            <td><span data-bind="text: Calf"></span></td>
    </tr>
</script>

Here is my KO JS:

<script type="text/javascript">

var data = $.getJSON('WeightTracker/List');

var viewModel = ko.mapping.fromJSON(data);

ko.mapping.updateFromJSON(viewModel, data);

ko.applyBindings(viewModel);

JSON getting back from the action:

{"ContentEncoding":null,"ContentType":null,"Data":[{"Id":1,"Weight":195.3,"Neck":10.3,"Chest":34.6,"Bicept":13.2,"Waist":34,"Hip":34,"Thigh":16.4,"Calf":8.8,"Date":"\/Date(1302554017067)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":2,"Weight":194.3,"Neck":10.157142857142858,"Chest":34.4,"Bicept":13,"Waist":33.5,"Hip":33.5,"Thigh":16.2,"Calf":8.6000000000000014,"Date":"\/Date(1302640417070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":3,"Weight":193.3,"Neck":10.014285714285714,"Chest":34.2,"Bicept":12.799999999999999,"Waist":33,"Hip":33,"Thigh":15.999999999999998,"Calf":8.4,"Date":"\/Date(1302726817070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":4,"Weight":192.3,"Neck":9.8714285714285719,"Chest":34,"Bicept":12.6,"Waist":32.5,"Hip":32.5,"Thigh":15.799999999999999,"Calf":8.2000000000000011,"Date":"\/Date(1302813217070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":5,"Weight":191.3,"Neck":9.72857142857143,"Chest":33.800000000000004,"Bicept":12.399999999999999,"Waist":32,"Hip":32,"Thigh":15.599999999999998,"Calf":8,"Date":"\/Date(1302899617070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":6,"Weight":190.3,"Neck":9.5857142857142872,"Chest":33.6,"Bicept":12.2,"Waist":31.5,"Hip":31.5,"Thigh":15.399999999999999,"Calf":7.8000000000000007,"Date":"\/Date(1302986017070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":7,"Weight":189.3,"Neck":9.4428571428571431,"Chest":33.4,"Bicept":12,"Waist":31,"Hip":31,"Thigh":15.2,"Calf":7.6000000000000005,"Date":"\/Date(1303072417070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":8,"Weight":188.3,"Neck":9.3,"Chest":33.2,"Bicept":11.799999999999999,"Waist":30.5,"Hip":30.5,"Thigh":14.999999999999998,"Calf":7.4,"Date":"\/Date(1303158817070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":9,"Weight":187.3,"Neck":9.1571428571428584,"Chest":33,"Bicept":11.6,"Waist":30,"Hip":30,"Thigh":14.799999999999999,"Calf":7.2000000000000011,"Date":"\/Date(1303245217070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":10,"Weight":186.3,"Neck":9.0142857142857142,"Chest":32.800000000000004,"Bicept":11.399999999999999,"Waist":29.5,"Hip":29.5,"Thigh":14.599999999999998,"Calf":7.0000000000000009,"Date":"\/Date(1303331617070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":11,"Weight":185.3,"Neck":8.8714285714285719,"Chest":32.6,"Bicept":11.2,"Waist":29,"Hip":29,"Thigh":14.399999999999999,"Calf":6.8000000000000007,"Date":"\/Date(1303418017070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":12,"Weight":184.3,"Neck":8.72857142857143,"Chest":32.4,"Bicept":11,"Waist":28.5,"Hip":28.5,"Thigh":14.2,"Calf":6.6000000000000005,"Date":"\/Date(1303504417070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":13,"Weight":183.3,"Neck":8.5857142857142872,"Chest":32.2,"Bicept":10.799999999999999,"Waist":28,"Hip":28,"Thigh":13.999999999999998,"Calf":6.4,"Date":"\/Date(1303590817070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":14,"Weight":182.3,"Neck":8.4428571428571431,"Chest":32,"Bicept":10.6,"Waist":27.5,"Hip":27.5,"Thigh":13.799999999999999,"Calf":6.2000000000000011,"Date":"\/Date(1303677217070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":15,"Weight":181.3,"Neck":8.3,"Chest":31.8,"Bicept":10.399999999999999,"Waist":27,"Hip":27,"Thigh":13.599999999999998,"Calf":6.0000000000000009,"Date":"\/Date(1303763617070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":16,"Weight":180.3,"Neck":8.1571428571428584,"Chest":31.6,"Bicept":10.2,"Waist":26.5,"Hip":26.5,"Thigh":13.399999999999999,"Calf":5.8000000000000007,"Date":"\/Date(1303850017070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":17,"Weight":179.3,"Neck":8.014285714285716,"Chest":31.400000000000002,"Bicept":10,"Waist":26,"Hip":26,"Thigh":13.2,"Calf":5.6000000000000005,"Date":"\/Date(1303936417070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":18,"Weight":178.3,"Neck":7.8714285714285719,"Chest":31.200000000000003,"Bicept":9.7999999999999989,"Waist":25.5,"Hip":25.5,"Thigh":12.999999999999998,"Calf":5.4,"Date":"\/Date(1304022817070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":19,"Weight":177.3,"Neck":7.7285714285714295,"Chest":31,"Bicept":9.6,"Waist":25,"Hip":25,"Thigh":12.799999999999999,"Calf":5.2000000000000011,"Date":"\/Date(1304109217070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"},{"Id":20,"Weight":176.3,"Neck":7.5857142857142863,"Chest":30.8,"Bicept":9.3999999999999986,"Waist":24.5,"Hip":24.5,"Thigh":12.599999999999998,"Calf":5.0000000000000009,"Date":"\/Date(1304195617070)\/","TimeOfDay":"Morning","DietBehavior":"Moderately"}],"JsonRequestBehavior":1}

I am now assuming I am completely wrong with this code as I am not recieving anything back but the JSON string. I have modified the code in so many different ways and I have been working on this for over 2 weeks trying to get this to work so if someone can explain to me what I am doing wrong apposed to sending me to knockoutjs website examples which have not been helpful. Thank you in advance for your help and saving me from growing even more gray hairs :/

PS. too add to this also.. I would like to use this mvcextension that a friend created which i had working but i had to do something like data.WeightStats or something.. so frustrated :/ check it out

public static MvcHtmlString KnockoutForModel<TModel>(this AjaxHelper<TModel> helper, bool includeScriptTags = true, bool? applyKoBindings = null)
    {
        var serializer = new JavaScriptSerializer();

        var json = "var viewModel = ko.mapping.fromJS(" + serializer.Serialize(helper.ViewData.Model) + ");\r\n";

        if (applyKoBindings.GetValueOrDefault(includeScriptTags))
        {
            json += "ko.applyBindings(viewModel);\r\n";
        }

        if (includeScriptTags)
        {
            json = "<script type=\"text/javascript\">\r\n" + json + "</script>\r\n";
        }

        return MvcHtmlString.Create(json);
    }

Answers


$.getJSON requires you to pass a callback to deal with the result, as the request is done asynchronously. So, you would want to do something like:

var viewModel = {};

$.getJSON('WeightTracker/List', function(result) {
    viewModel.stats = ko.mapping.fromJS(result.Data);
    ko.applyBindings(viewModel);
});

Then, based on above your template binding would look like:

<tbody data-bind='template: {name: "statRowTemplate", foreach: stats }'></tbody>

So, when you do $.getJSON, in the callback you will be dealing with a JavaScript object and not a JSON string.

Would be happy to help you out, if you have additional issues.


Need Your Help

How to include emoticons in Swift string?

string swift nsstring

Here is a pretty good article that references iOS emoticons and their code. For example \ue008 for the small camera.

Converting string to title case

c# string

I have a string which contains words in a mixture of upper and lower case characters.