如何使用敲除来遍历对象(而不是数组)

我想使用类似于Knockout的foreach构造来迭代对象的属性。 这是我正在创造的…

期望的结果

<table> <tr> <td>Name 1</td> <td>8/5/2012</td> </tr> <tr> <td>Name 2</td> <td>2/8/2013</td> </tr> </table> 

但是,我的模型看起来像这样…

JS

 function DataModel(){ this.data = ko.observableArray([{ entityId: 1, props: { name: 'Name 1', lastLogin: '8/5/2012' } }, { entityId: 2, props: { name: 'Name 2', lastLogin: '2/8/2013' } }]); } var dataModel = new DataModel(); ko.applyBindings(dataModel); 

每行都有一个entityId和道具,它们本身就是一个对象。 此模板不起作用,但是如何将其更改为生成上面所需的表格?

编辑:在这个例子中的propsnamelastLogin ,但我需要一个解决scheme,不知道什么是包含在props

我也有这个FIDDLE 。

HTML

 <div data-bind="template: { name: 'template', data: $data }"></div> <script type="text/html" id="template"> <table> <tr data-bind="foreach: data()"> <td data-bind="text: entityId"></td> </tr> </table> </script> 

你总是可以创build一个绑定处理程序来处理转换。

 ko.bindingHandlers.foreachprop = { transformObject: function (obj) { var properties = []; ko.utils.objectForEach(obj, function (key, value) { properties.push({ key: key, value: value }); }); return properties; }, init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { var properties = ko.pureComputed(function () { var obj = ko.utils.unwrapObservable(valueAccessor()); return ko.bindingHandlers.foreachprop.transformObject(obj); }); ko.applyBindingsToNode(element, { foreach: properties }, bindingContext); return { controlsDescendantBindings: true }; } }; 

然后应用它:

 <div data-bind="template: { name: 'template', data: $data }"></div> <script type="text/html" id="template"> <table> <tbody data-bind="foreach: data"> <tr data-bind="foreachprop: props"> <td data-bind="text: value"></td> </tr> </tbody> </table> </script> 

在现代浏览器中(或使用适当的polyfill),您可以遍历Object.keys(obj) (该方法只返回自己的枚举属性 ,这意味着不需要额外的hasOwnProperty检查):

 <table> <tbody data-bind="foreach: {data: data, as: '_data'}"> <tr data-bind="foreach: {data: Object.keys(props), as: '_propkey'}"> <th data-bind="text: _propkey"></th> <td data-bind="text: _data.props[_propkey]"></td> </tr> </tbody> </table> 

弄乱 。

注:我只是好奇,看看这是否会工作,上面的模板比我想用在生产(或回来几个月后,像“跆拳道”)污染更多。

自定义绑定将是一个更好的select,我个人的偏好,虽然将使用计算的可观察或可写的计算观察 (当使用json响应a-la restful api时,后者将是方便的)。

这是对杰夫答案的修改,保留了绑定上下文

 ko.bindingHandlers.eachProp = { transformObject: function (obj) { var properties = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { properties.push({ key: key, value: obj[key] }); } } return ko.observableArray(properties); }, init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { var value = ko.utils.unwrapObservable(valueAccessor()), properties = ko.bindingHandlers.eachProp.transformObject(value); ko.bindingHandlers['foreach'].init(element, properties, allBindingsAccessor, viewModel, bindingContext) return { controlsDescendantBindings: true }; }, update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { var value = ko.utils.unwrapObservable(valueAccessor()), properties = ko.bindingHandlers.eachProp.transformObject(value); ko.bindingHandlers['foreach'].update(element, properties, allBindingsAccessor, viewModel, bindingContext) return { controlsDescendantBindings: true }; } }; 

现在申请与父母和根:

 <table> <tbody data-bind="foreach: data"> <tr data-bind="eachProp: props"> <td data-bind="text: value, click: $root.doSomething"></td> </tr> </tbody> </table> 
 <table> <tr data-bind="foreach: {data: data, as: 'item'}"> <td data-bind="foreach: { data: Object.keys(item), as: 'key' }"> <b data-bind="text: item[key]"></b> </td> </tr> </table> function DataModel(){ this.data = ko.observableArray([{ entityId: 1, props: { name: 'Name 1', lastLogin: '8/5/2012' } }, { entityId: 2, props: { name: 'Name 2', lastLogin: '2/8/2013' } }]); } var dataModel = new DataModel(); ko.applyBindings(dataModel); 

希望这是有益的(赦免简洁)

附录:

这是一个正在testing的工作示例…

 <table class="table table-hover"> <thead> <tr> <!-- ko foreach: gridOptions.columnDefs --> <th data-bind="text: displayName"></th> <!-- /ko --> </tr> </thead> <tbody> <!-- ko foreach: {data: gridOptions.data, as: 'item'} --> <tr> <!-- ko foreach: {data: Object.keys(item), as: 'key'} --> <td> <span data-bind="text: item[key]"></span> </td> <!-- /ko --> </tr> <!-- /ko --> </tbody> </table> 

假设有一个更深层次的问题( 请参阅Google群组的这个线程 ),那就是foreach将对象视为参数字典,而不是要迭代的集合。

到目前为止,我的最佳解决scheme是将foreach合并到Object.keys(myobject)和'with'绑定上下文中。

(不是严格的迭代属性,而是创build上面的表)

 <div data-bind="template: { name: 'template', data: $data }"></div> <script type="text/html" id="template"> <table data-bind="foreach: data()"> <tr> <td data-bind="text: props.name"></td> <td data-bind="text: props.lastLogin"></td> </tr> </table> </script> 

更新: http : //jsfiddle.net/cwnEE/7/

使用任何基本对象的简单答案,为我工作:

 <!-- ko foreach: {data: Object.keys(myObj)} --> <span data-bind="text: $data"></span> <span data-bind="text: $parent.myObj[$data]"></span> <!-- /ko -->