【问题标题】:Knockout foreach binding displays only the first virtual element dataKnockout foreach 绑定只显示第一个虚拟元素数据
【发布时间】:2012-11-04 11:37:36
【问题描述】:

在网格上列出虚拟元素属性时,我遇到了淘汰赛的 foreach 绑定问题。

虽然 web api 按预期返回 JSON 数据,但敲除未正确显示虚拟元素属性。

我的 UI 显示产品列表,其中一个列是 ProductCategory.Name。由于某种原因,它只显示每个产品类别的第一次出现。

名称类别 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 数据出现一次,然后被同一类别的下一个产品引用。

关于如何解决此问题以显示网格上所有元素的类别名称的任何建议?

【问题讨论】:

  • 你能展示一下发送给客户端的 JSON 是什么样子的吗?
  • 我将使用 JSON 更新问题。但我相信没关系。

标签: asp.net-mvc knockout.js asp.net-web-api


【解决方案1】:

您的 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

【讨论】:

  • 谢谢肯尼斯!我想知道淘汰赛是否能理解这一点。
  • 但是,在这种情况下你有什么建议?我正在关注本教程(asp.net/web-api/overview/creating-web-apis/…),但它太简单了。在现实世界的应用程序中,我遇到了很多问题。
  • Kenneth Json 是由 MVC4 web api 创建的。
  • 用修复更新了答案。
  • 两种解决方案都能解决问题。 Jeff's one 非常有趣,因为它避免了数据复制和循环引用。但是,正如建议的那样,为了简单起见,我将采用 Kenneth 的解决方案,直到我需要处理循环引用。
【解决方案2】:

您需要根据它们的 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>

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    相关资源
    最近更新 更多