如何使用knockout在动态添加的属性上绑定嵌套的foreach循环?

时间:2014-03-13 20:48:17

标签: json knockout.js knockout-mapping-plugin

我有一系列物品。这些项目分为"类型"然后在类型中进一步划分为"类别"。我不知道"类型的名字"或者"类别"事先。

我想做一些嵌套的foreach绑定来分层表示数据。像这样:

<ul data-bind="foreach: OrderItems.Types">
<li>
    ItemType: <span data-bind='text: $data'></span>
    <ul data-bind="foreach: Categories">
      <li>
        Category: <span data-bind='text: $data'></span>
        <ul data-bind="foreach: OrderItems">
          <li>
            Item: <span data-bind="text: Name"> </span>
          </li>
        </ul>              
      </li>
    </ul>
</li>

var order = {
"OrderNumber": "394857",
"OrderItems": {
    "Types": {
        "Services": {
            "Categories": {
                "carpet cleaning": {
                    "OrderItems": [
                        {
                            "OrderItemID": "9d398f88-892c-11e3-8f31-18037335d26a",
                            "Name": "ARug-Oriental Rugs (estimate on site)"
                        },
                        {
                            "OrderItemID": "9d398f53-892c-11e3-8f31-18037335d26a",
                            "Name": "C1-Basic Cleaning  (per room)"
                        },
                        {
                            "OrderItemID": "9d398f54-892c-11e3-8f31-18037335d26a",
                            "Name": "C2-Clean & Protect  (per room)"
                        },
                        {
                            "OrderItemID": "9d398f55-892c-11e3-8f31-18037335d26a",
                            "Name": "C3-Healthy Home Package (per room)"
                        }
                    ]
                },
                "specialty": {
                    "OrderItems": [
                        {
                            "OrderItemID": "9d398f8f-892c-11e3-8f31-18037335d26a",
                            "Name": "SOTHR-Other"
                        }
                    ]
                },
                "tile & stone": {
                    "OrderItems": [
                        {
                            "OrderItemID": "9d398f8e-892c-11e3-8f31-18037335d26a",
                            "Name": "TILE-Tile & Stone Care"
                        }
                    ]
                },
                "upholstery": {
                    "OrderItems": [
                        {
                            "OrderItemID": "9d398f7b-892c-11e3-8f31-18037335d26a",
                            "Name": "U3S1-Upholstery - Sofa (Seats 3: 7 linear feet)"
                        },
                        {
                            "OrderItemID": "9d398f7c-892c-11e3-8f31-18037335d26a",
                            "Name": "U3S2-Upholstery - Sofa - Clean & Protect (Seats 3: 7 linear feet"
                        }
                    ]
                }
            }
        },
        "Products": {
            "Categories": {
                "carpet cleaning": {
                    "OrderItems": [
                        {
                            "OrderItemID": "9d398f84-892c-11e3-8f31-18037335d26a",
                            "Name": "PLB-Leave Behind Item"
                        }
                    ]
                }
            }
        }
    }
}
};

var viewModel = ko.mapping.fromJS(order);
ko.applyBindings(viewModel);

这里是上述代码的小提琴:http://jsfiddle.net/mattlokk/6Q5f7/5/

1 个答案:

答案 0 :(得分:2)

要绑定您的结构,您需要将对象转换为数组。鉴于您正在使用映射插件,最简单的方法可能是使用绑定将具有属性的对象转换为键/值数组。

以下是示例绑定:

ko.bindingHandlers.objectForEach = {
    init: function(element, valueAccessor, allBindings, data, context) {
        var mapped = ko.computed({
            read: function() {
                var object = ko.unwrap(valueAccessor()),
                    result = [];

                ko.utils.objectForEach(object, function(key, value) {
                    var item = {
                        key: key,
                        value: value
                    };

                    result.push(item);
                });


                return result;
            },
            disposeWhenNodeIsRemoved: element
        });

        //apply the foreach bindings with the mapped values
        ko.applyBindingsToNode(element, { foreach: mapped }, context);

        return { controlsDescendantBindings: true };   
    }
};

这将创建一个即时计算,将对象映射到键/值数组。现在,您可以使用objectForEach代替foreach来对付您的对象。

以下是一个基本示例:http://jsfiddle.net/rniemeyer/nn3jg/以下是您的小提琴示例:http://jsfiddle.net/rniemeyer/47Wbe/