在网格上列出虚拟元素属性时,我遇到了淘汰赛的foreach绑定问题。
虽然web api按预期返回JSON数据,但是knockout并未正确显示虚拟元素属性。
我的UI显示产品列表,其中一个列是ProductCategory.Name
。由于某种原因,它只显示每个产品类别的第一个外观。
Name Category Pr01 Cat01 Pr02 Pr03 Cat02 Pr04 Cat03 Pr05
第2和第5产品也是“Cat01”类别的产品。但由于某种原因,它没有显示出来。
我有以下型号:
public class Product
{
[ScaffoldColumn(false)]
public int ProductId { get; set; }
public string Name { get; set; }
public int ProductsCategoryId { get; set; }
public virtual ProductsCategory ProductCategory { get; set; }
}
public class ProductsCategory
{
public int ProductsCategoryId { get; set; }
public string Name { get; set; }
}
这就是我绑定网格的方式:
<tbody data-bind="foreach: products">
<tr>
<td class="left" data-bind="text: $data.Name"></td>
<td class="left" data-bind="text: $data.ProductCategory.Name"></td>
</tr>
</tbody>
这是JSON:
[{
"$id": "1",
"ProductCategory": {
"$id": "2",
"ProductsCategoryId": 1,
"Reference": "OSOL ",
"Name": "Óculos de Sol",
"ProductsCategoryStatusId": 1
},
"ProductId": 3,
"Reference": "HTHTOD ",
"BarCode": "2122071530085 ",
"Name": "Thin Hard Trivex OD",
"Description": null,
"ProductsBrandId": 1,
"ProductsCategoryId": 1,
"ProductsSupplierId": 1,
"ProductStatusId": 1
}, {
"$id": "3",
"ProductCategory": {
"$ref": "2"
},
"ProductId": 4,
"Reference": "HTHTOE ",
"BarCode": "2122071531163 ",
"Name": "Thin Hard Trivex OE",
"Description": "null",
"ProductsBrandId": 1,
"ProductsCategoryId": 1,
"ProductsSupplierId": 1,
"ProductStatusId": 1
}, {
"$id": "4",
"ProductCategory": {
"$id": "5",
"ProductsCategoryId": 2,
"Reference": "OGRAU ",
"Name": "Óculos de Grau",
"ProductsCategoryStatusId": 1
},
"ProductId": 10,
"Reference": "HTHTOX ",
"BarCode": "2123180206342 ",
"Name": "Thin Hard Trivex OX",
"Description": null,
"ProductsBrandId": 2,
"ProductsCategoryId": 2,
"ProductsSupplierId": 1,
"ProductStatusId": 1
}, {
"$id": "6",
"ProductCategory": {
"$id": "7",
"ProductsCategoryId": 3,
"Reference": "LNTS ",
"Name": "Lentes",
"ProductsCategoryStatusId": 1
},
"ProductId": 16,
"Reference": "HTHTOY ",
"BarCode": "2123192208431 ",
"Name": "Thin Hard Trivex OY",
"Description": null,
"ProductsBrandId": 4,
"ProductsCategoryId": 3,
"ProductsSupplierId": 1,
"ProductStatusId": 1
}, {
"$id": "8",
"ProductCategory": {
"$ref": "2"
},
"ProductId": 12,
"Reference": "HTHTOZ ",
"BarCode": "2123192059538 ",
"Name": "Thin Hard Trivex OZ",
"Description": null,
"ProductsBrandId": 1,
"ProductsCategoryId": 1,
"ProductsSupplierId": 1,
"ProductStatusId": 1
}]
如您所见,ProductsCategory
数据出现一次,然后由同一类别中的下一个产品引用。
有关如何解决这个问题的建议,以显示网格上所有元素的类别名称?
答案 0 :(得分:0)
你的json采用的是淘汰赛无法理解的格式。产品类别仅传输一次,第二次传输产品类别时,它包含第一个“参考”。
请参阅ID为3的对象,如下所示(错误示例)。
"$id":"3",
"ProductCategory":{"$ref":"2"}
以下是正确的。
"$id":"1",
"ProductCategory":{"$id":"2","ProductsCategoryId":1,"Reference":"OSOL ","Name":"Óculos de Sol","ProductsCategoryStatusId":1}
更新:如何处理上面的非标准json。
我看了一下示例项目。它在\ ProductStore \ App_Start \ WebApiConfig.cs
中有以下内容var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
根据这个http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization,保留对象引用会产生非标准的json,大多数客户端都不会使用它。
获得标准的json,这将允许敲除工作。
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.None; //this needs to be None
答案 1 :(得分:0)
您需要从其ID中创建ProductCategory
个对象的映射。这样,当您渲染类别时,您可以从地图中获取正确的类别。
您可以将产品映射到解析引用的位置,也可以创建一个根据需要解析这些引用的函数。我为这个例子选择了后一种方法。
function ViewModel(data) {
var self = this,
productCategories = function (products) {
var map = {};
// throw all categories (with ids) into the map
ko.utils.arrayForEach(products, function (item) {
var category = item.ProductCategory;
if (category.$id) map[category.$id] = category;
});
return map;
} (data.products);
self.products = ko.observableArray(data.products);
self.getProductCategory = function (product) {
var productCategory = product.ProductCategory,
ref = productCategory.$ref;
// get the referenced category
if (ref) productCategory = productCategories[ref];
return productCategory;
}
}
然后像这样绑定它:
<tbody data-bind="foreach: products">
<tr>
<td class="left" data-bind="text: Name"></td>
<td class="left" data-bind="text: $root.getProductCategory($data).Name"></td>
</tr>
</tbody>