Reputation: 798
I've been trying to follow the tutorials for Knockout.js in order to render a table in my view. My controller is retrieving a list of records as an IEnumerable type and sending to the view. I'm trying to get Knockout mapping to work to display my records in an HTML Table.
My model looks like:
public class ImportItem
{
public string LName { get; set; }
public string FName { get; set; }
public string HPhone { get; set; }
public string EMailAddress { get; set; }
public string OtherPhone { get; set; }
}
I can't seem to pass the IEnumerable to the View and get even a simple table with just LName and FName to display. Does anyone have any sample code using knockout mapping that I can look at?
Solved Below
At the top of my view I added:
@model IEnumerable<MyProject.Models.ImportItem>
@{
var jsonData = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));
}
My javascript:
$(function () {
var viewModelJSON = ko.mapping.fromJSON('@Html.Raw(jsonData)');
ko.applyBindings(viewModelJSON);
});
My html binding, the $data winded up being the key to reference the unnamed array:
<table>
<thead><tr>
<th>Last Name</th>
</tr></thead>
<tbody data-bind="foreach: $data">
<tr>
<td data-bind="text: LName"></td>
</tr>
</tbody>
</table>
Upvotes: 3
Views: 2750
Reputation: 1923
The mapping plugin is intended for mapping from a javascript (JSON) object. What you can do is in the controller, serialize all the data you need to send into a JSON string and set that as an attribute of the model you send to the view:
public class MyModel
{
public string JsonData { get; set; }
}
After the your data has been generated you can use a serializer (many exist, in the example below I use Json.NET) to convert it to a JSON string.
model.JsonData = JsonConvert.SerializeObject(importItems);
Then in your view, you can use the mapping plugin to map your JSON object, using json2.js for parsing the string and converting it to JSON.
<script type="text/javascript">
var viewModel = ko.mapping.fromJS($.parseJSON('@Html.Raw(Model.JsonData)'));
ko.applyBindings(viewModel);
</script>
Alternatively, you could send your IEnumerable
of models to the view the same way you have in your question, and serialize them with Razor in the view (rather than in the controller) before doing the javascript parsing and mapping. This would probably be the better way if you want to follow the MVC pattern as strictly as possible.
So before the <script>
block, you could open up a block of razor code and declare a variable to hold the serialized IEnumerable, so something like this:
@{
string jsonData = JsonConvert.SerializeObject(Model);
}
Then in the javascript block:
var viewModel = ko.mapping.fromJS($.parseJSON('@Html.Raw(jsonData)'));
To know what attributes to bind your data-bind="foreach ..."
tags to, you may have to do some debugging in the javascript to inspect the viewModel object and see how exactly the mapping plugin mapped your IEnumerable<ImportItems>
. I've only ever done this with a single model, so I'm really not sure what would happen.
Upvotes: 2