Note that there are some explanatory texts on larger screens.

plurals
  1. POKnockout Master/Detail object from JSON with template and function
    primarykey
    data
    text
    <p>I've recently started working with Knockout and most things have worked quite easily. However, this one has me a little stumped and was hoping someone could provide some help. I'm creating my Knockout model by serializing a JSON object that has a Master/Detail structure, which I suspect is causing some of my problem. I can bind/render the master portion of the record, and I can bind and render the details using a foreach template. However, in my scenario I want the user to select a detail record to edit from the child list. Problem is I can't get the selection to work. I'm getting the click event to fire and it appears that my detail record is being passed to my event - except that I can't read the value of the properties. Looking in fiddler it appears the object that is coming through is a function call of the event. Not really sure at this point. So, this is my setup</p> <p>My JSON </p> <pre><code>{ "Height":"250", "Width":"200", "Speed":"700", "Pause":"4", "ShowItems":"1", "Animation":"fade", "MousePause":"true", "IsPaused":"false", "Direction":"up", "DataItems":[{ "OrderId":1, "ItemHtml":"This is item 1" },{ "OrderId":2, "ItemHtml":"This is item 2" },{" OrderId":3, "ItemHtml":"This is item 3" }] } </code></pre> <p>Javascript to serialize JSON object</p> <pre><code>var viewModel = { vmRotator: ko.mapping.fromJSON(jsonObj) //-- THIS IS WHERE I THINK THE PROBLEM IS , selectRotatorItem: function (item) { //alert(item.OrderId); // THIS DOES NOT WORK console.log(item); } } ko.applyBindings(viewModel); //-- hookup the click event for templated items $("#rotatorItems").on("click", ".sel", function () { var data = ko.dataFor(this); viewModel.selectRotatorItem(data); //-- call to object function }); </code></pre> <p>HTML to display the items, provide button to click</p> <pre><code>&lt;table id="rotatorList" width="100%" border="0" cellspacing="0" cellpadding="2"&gt; &lt;tbody id="rotatorItems" data-bind="template: { foreach: vmRotator.DataItems }"&gt; &lt;tr&gt; &lt;td style="width: 20px;"&gt; &lt;input type="button" class="sel" value="Select" /&gt; &lt;span data-bind="text: OrderId"&gt;&lt;/span&gt; &lt;/td&gt; &lt;td style="width: 90%;" data-bind="text: ItemHtml"&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; </code></pre> <p>Best I can tell this is all working correctly. My event is being called but when I look at the result in the console it looks like the text of a function rather than a value.</p> <p>In the function:</p> <pre><code>, selectRotatorItem: function (item) { //alert(item.OrderId); // THIS DOES NOT WORK console.log(item); } </code></pre> <p>alert(item.OrderId) displays:</p> <pre><code>"function d(){if(0&lt;arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c}" </code></pre> <p>Rather than a number like 1 or 2 which is the value of Order ID. Not sure why this is but I've done something wrong.</p> <p>I've kinda hacked together this code from viewing several examples that are similar to what I'm doing. I could be going about this the wrong way altogether but I think I'm just missing something simple. I'm sure some of the Javascrtipt gods out there can easily see what I don't so I'd appreciate your help.</p> <hr> <h2>In response to Rune's answer to my original question, here is the final version that works</h2> <p>Javascript code to build bindings</p> <pre><code>//-- define models: master and detail modesl var viewRotatorItemModel = { 'Height': ko.observable(), 'Width': ko.observable() }; var viewRotatorModel = { 'Height': ko.observable(), 'Width': ko.observable(), 'Speed': ko.observable(), 'ShowItems': ko.observable(), 'Animation': ko.observable(), 'IsPaused': ko.observable(), 'Direction': ko.observable(), 'UseEditor': ko.observable(), 'HtmlData': ko.observable(), 'DataItems': { create: function (options) { return new viewRotatorDataItem(options.data); } } }; //-- define objects around models var viewRotatorDataItem = function (data) { var self = this; //--&gt; IMPORTANT TO USE fromJS as JSON is already an object ko.mapping.fromJS(data, viewRotatorItemModel, self); self.selectItem = function () { alert("item with id " + self.OrderId() + " clicked"); }; }; var ViewModel = function (data) { var self = this; //--&gt; IMPORTANT TO USE fromJSON as incoming object is JSON text ko.mapping.fromJSON(data, viewRotatorModel, self); }; ... ... //-- create objects when ready vmRotator = new ViewModel(jsonObj); ko.applyBindings(vmRotator); </code></pre> <p>HTML to display Master/Detail items</p> <pre><code>&lt;h4&gt;Main Items&lt;/h4&gt; &lt;input type="text" id="wc_Height" data-bind="value: vmRotator.Height" /&gt; &lt;input type="text" id="wc_Width" data-bind="value: vmRotator.Width" /&gt; &lt;h3&gt;Detail Items&lt;/h3&gt; &lt;table id="rotatorList" width="100%" border="0" cellspacing="0" cellpadding="2"&gt; &lt;tbody id="rotatorItems" data-bind="template: { foreach: vmRotator.DataItems }"&gt; &lt;tr&gt; &lt;td style="width: 20px;"&gt; &lt;input type="button" value="Select" data-bind="click: selectItem" /&gt; &lt;span data-bind="text: OrderId"&gt;&lt;/span&gt; &lt;/td&gt; &lt;td style="width: 90%;" data-bind="text: ItemHtml"&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload