0
votes

I am just beginning to learn KnockoutJS so I am probably missing something simple but here is my issue.

Below is my ClassType class

public class ClassType
{
    [HiddenInput(DisplayValue = false)]
    public int ID { get; set; }

    [Required(ErrorMessage = "Please enter a description")]
    public string Description { get; set; }

    [Display(Name = "Class Slots")]
    public int ClassSlots { get; set; }
}

I have a method in my controller to return a list of all the types set up called GetAll

public JsonResult GetAll()
    {
        var classtypes = classtypeRepository.All;
        return Json(classtypes, JsonRequestBehavior.AllowGet);
    }

In my view I have the following code to load the data into my viewmodel

<script type="text/javascript">
$(document).ready(function () {
    $.get("/ClassTypes/GetAll/", "", function (data) {
        var viewModel = {
            classtypes: ko.observableArray()
        };
        viewModel.classtypes = ko.mapping.fromJS(data);
        ko.applyBindings(viewModel);
    });
});
</script>

I have thrown the following div into my view to make sure something is returned

<div data-bind="text: ko.toJSON($data)"></div>

The following is returned

{"classtypes":[{"ID":1,"Description":"Online","ClassSlots":30},{"ID":2,"Description":"In-House","ClassSlots":15},{"ID":3,"Description":"Hands-On","ClassSlots":10}]}

If I try to bind anything to the view model it does not seem to understand the properties

 <tbody>
    <!-- ko.foreach: classtypes -->
         <tr>
            <td></td>
            <td data-bind="text: Description">
            </td>
            <td data-bind="text: ClassSlots">
            </td>
        </tr>
    <!-- /ko -->
</tbody>

I used the knockoutJS mapping plugin to bring the data in which I thought would create the structure of the viewmodel for me. What am I missing?

1
Please try to do the following: <td data-bind="text: $data.Description"> - Pavlo
that did not work for me. I get the same results - Dave Wade
OK I found a solution but maybe someone can tell em why this worked. I am using knockout 2.2.0 which i thought supported control flow templates but that seems to be the problem. If I take otu the comments and on the tbody tag put <tbody data-bind="foreach: classtypes"> the data shows up - Dave Wade
I've updated my answer which should answer your last question regarding foreach comment - Pavlo
If you've ended up here because your parent property is undefined, breaking your bindings, see my answer here (sorry for the notification, OP!) - user1228

1 Answers

1
votes

Your code is correct except one thing.
To get the specific property from Array you should call $data.YOUR_SPECIFIC_PROPERTY_NAME
HTML CODE:

<table style="border: 1px solid #222;">
  <tr data-bind="foreach: classtypes">
    <td></td>
    <td data-bind="text: $data.Description"></td>
    <td data-bind="text: $data.ClassSlots"></td>
  </tr>
</table>


Javascript CODE

var ViewModel = function(data) {
  var self = this;
  self.classtypes = ko.observableArray(initialData);
};

var initialData = [{"ID":1,"Description":"Online","ClassSlots":30},
                   {"ID":2,"Description":"In-House","ClassSlots":15},
                   {"ID":3,"Description":"Hands-On","ClassSlots":10}];

ko.applyBindings(new ViewModel(initialData));


Also I've created jsFiddle for you Click here to see the DEMO


START UPDATE
Also it works with foreach comments, but you've one typo in ko.foreach comment, actually you should change a dot ('.') to empty space (' ') like this <!-- ko foreach --> , also here will be your correct HTML Code:

<table style="border: 1px solid #222;">
  <tbody>
    <!-- ko foreach: classtypes -->
    <tr >
      <td></td>
      <td data-bind="text: $data.Description"></td>
      <td data-bind="text: $data.ClassSlots"></td>
    </tr>
    <!-- /ko -->
  <tbody>
</table>

END UPDATE