简体   繁体   中英

Unable to map .json data in knockoutJS viewmodel

I have this small MVC application that makes .ajax call, gets data in .json format and display the response in html. I am new to knockoutJS and I am having a problem mapping the json format into the model.

I am able to map the json data I received upon the .ajax call into an array ( categories ) but when I try to add it to shoppingCart array it doesn't show the mapped data.

Can some one help me why the data is lost by the time it tries to add it to shoppingCart collection?

Database Tables:

Product
Id | Name | Price|
1  | Buns  | 1.00

ProductTag
Id | Name       | Fk_Product_Id|
1  | Baked Goods| 1

/* Fk_Product_Id - points to Product Id */

Response in Json format:

{
  "Data": [
    {
      "ProductTags": [
        {
          "Id": 1,
          "Name": "Baked Goods",
          "Fk_Product_Id": 1
        },
        {
          "Id": 2,
          "Name": "Hot Dogs",
          "Fk_Product_Id": 1
        }
      ],
      "Id": 1,
      "Name": "Buns",
      "Price": 1.00
    }           
  ],
}

js file:

var categories = [];
$.ajax({
    url: 'ShoppingCart/GetAllProducts',
    cache: false,
    type: 'GET',
    contentType: 'application/json; charset=utf-8',
    data: {},
    success: function (data) {
        // I had to map the data to model manually. 
        // Ko.mapper didn't work for me.
        var parsed = JSON.parse(data);
        var product = parsed.Data;
        console.log(parsed);
        for (var i = 0; i < product.length; i++) {
            var id = product[i].Id;
            var name = product[i].Name;
            var price = product[i].Price;
            var productTag = product[i].ProductTags;
            categories.push(new Product(id, name, price,productTag));
        }
    }
});

function Product(id, name, price, productTags) {
    var self = this;
    self.id = ko.observable(id),
    self.name = ko.observable(name);
    self.price = ko.observable(price);
    self.productTags = typeof (productTags) !== "undefined" ? productTags : [];
    self.productTags = ko.observableArray(productTags);
}

function PersonViewModel() {
    var self = this;
    self.firstName = ko.observable("John");
    self.lastName = ko.observable("Smith");
    self.checkout = function () {
        alert("Trying to checkout");
    };

    self.shoppingCart = ko.observableArray(categories);

};
//var viewModel = new PersonViewModel();
//ko.applyBindings(viewModel);
var viewModel = new PersonViewModel();
ko.applyBindings(viewModel, document.getElementById('shoppingCart'));

Html:

<div id="shoppingCart">
   <table>
        <thead><tr>
            <th>Item number</th>
            <th>Product</th>
            <th>Price</th>
            <th>Tags</th>
            <th>Action</th>
        </tr></thead>
        <tbody data-bind='foreach: shoppingCart'>
        <tr>
            <td data-bind='text: $index'></td>
            <td data-bind='text: name'></td>
            <td data-bind='text: price'></td>
            <td>
                <ul data-bind="foreach: productTags">
                    <li data-bind="text:$data">
                    </li>
                </ul>
            </td>

            <td>
                <button data-bind='click: $root.removeProduct'>Remove</button>
            </td>
        </tr>
        </tbody>
    </table>
</div>

You're just updating a local variable called categories and not the viewmodel's observableArray property. Instead, loop through Data and push to viewModel.shoppingCart .

 setTimeout(() => { const response = {"Data":[{"ProductTags":[{"Id":1,"Name":"Baked Goods","Fk_Product_Id":1},{"Id":2,"Name":"Hot Dogs","Fk_Product_Id":1}],"Id":1,"Name":"Buns","Price":1.00}],} response.Data.forEach(p => { // push to observableArray viewModel.shoppingCart.push(new Product(p.Id, p.Name, p.Price, p.ProductTags)) }) }, 2000) function Product(id, name, price, productTags) { var self = this; self.id = ko.observable(id); self.name = ko.observable(name); self.price = ko.observable(price); let tags = typeof(productTags) !== "undefined" ? productTags : []; self.productTags = ko.observableArray(tags); } function PersonViewModel() { var self = this; self.firstName = ko.observable("John"); self.lastName = ko.observable("Smith"); self.shoppingCart = ko.observableArray([]); // initialize to empty array }; var viewModel = new PersonViewModel(); ko.applyBindings(viewModel); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <table> <thead> <tr> <th>Item number</th> <th>Product</th> <th>Price</th> <th>Tags</th> <th>Action</th> </tr> </thead> <tbody data-bind='foreach: shoppingCart'> <tr> <td data-bind='text: $index'></td> <td data-bind='text: name'></td> <td data-bind='text: price'></td> <td> <ul data-bind="foreach: productTags"> <li data-bind="text:Name"> </li> </ul> </td> <td> <button data-bind='click: $root.removeProduct'>Remove</button> </td> </tr> </tbody> </table> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM