首页 > 解决方案 > 无法在 knockoutJS 视图模型中映射 .json 数据

问题描述

我有这个小型 MVC 应用程序,它可以进行 .ajax 调用,以 .json 格式获取数据并以 html 格式显示响应。我是 knockoutJS 的新手,我在将 json 格式映射到模型时遇到问题。

我能够将我在 .ajax 调用时收到的 json 数据映射到一个数组(categories)中,但是当我尝试将它添加到shoppingCart数组时,它不会显示映射的数据。

有人可以帮助我为什么在尝试将数据添加到shoppingCart集合时丢失数据吗?

数据库表:

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 */

Json 格式的响应:

{
  "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 文件:

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>

标签: javascriptknockout.js

解决方案


您只是在更新一个名为的局部变量categories,而不是 viewmodel 的observableArray属性。相反,循环Data并推送到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>


推荐阅读