Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout observableArray is not binding correctly

I am in the process of learning about knockout/json/mvc et al and have tried to put together an example project, but for some reason I am unable to get the data to bind correctly.

In the code snippet below, I get some JSON data from a web server and then try to map it to a function and then eventually to my knockout observableArray. What I then do is use this observableArray to bind to a HTML table. However the HTML table is not displaying any data. I put a label on to the HTML page and this does print out but with a toString() value of : [Object object] five times, which matches the amount of properties in the JSON data.

Can anyone see anything obvious I am missing?

JSON received from web server:

{ "Id": 1, "Name": "Inst123", "Price": 10, "DateTime": "2014-01-16T17:22:43.6383507+00:00", "Description": "Descriptions" };

.

ViewModel

$(document).ready(function () {
    var gtViewModel = new GvTradeViewModel();
    ko.applyBindings(gtViewModel);
    console.log("ViewModel created");
});

    var GvTradeViewModel = function () {
    var self = this;
    self.gvTrades = ko.observableArray([]);

    var apiUrl = "http://localhost:57858/api/Trade/1";

    console.log("Starting JSON data retrieval from: " + apiUrl);

    $.getJSON(apiUrl)
       // Handle success event.
      .done(function (jsonData) {
          if (jsonData.isEmptyObject)
              console.log("NoData recieved");
          else {
              console.log("JSON data: " + jsonData);

              var mappedTrades = $.map(jsonData, function (gvTradeData) {
                  return new GvTrade(gvTradeData);
              });
              self.gvTrades(mappedTrades);
              console.log(self.gvTrades);

          }
      })
      // Handle error/fail event.
     .fail(function (jqxhr, textStatus, error) {
         var err = textStatus + ", " + error;
         console.log("Request Failed: " + err);
     });
};

function GvTrade(data) {
    this.TradeId = ko.observable(data.TradeId);
    this.InstrumentName = ko.observable(data.InstrumentName);
    this.DateTime = ko.observable(data.DateTime);
    this.Price = ko.observable(data.Price);
    this.Description = ko.observable(data.Description);
}

HTML

<table>
<thead>
    <tr>
        <th>TradeId</th>
        <th>InstrumentName</th>
        <th>Price</th>
        <th>DateTime</th>
        <th>Description</th>
    </tr>
</thead>
<tbody data-bind="foreach: $data.gvTrades">
    <tr>
        <td data-bind="text: InstrumentName"></td>
        <td data-bind="text: Price"></td>
        <td data-bind="text: DateTime"></td>
        <td data-bind="text: Description"></td>
    </tr>
</tbody>

like image 537
sridg Avatar asked Feb 07 '26 02:02

sridg


1 Answers

The JSON coming from your server represents a single object and not an array.

So when you are calling $.map then it does not correctly maps your data as an array, so you will end up some unusable objects.

To fix this you need to make sure that your jsonData containing an array before the map operation, you can do this with calling jQuery.makeArray on it (or you can have an if which is based on your data type decide whether you need to map or not):

var mappedTrades = $.map($.makeArray(jsonData), function (gvTradeData) {
    return new GvTrade(gvTradeData);
});

Demo JSFiddle.

like image 101
nemesv Avatar answered Feb 09 '26 16:02

nemesv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!