如何使用敲除来遍历对象(而不是数组)
我想使用类似于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和道具,它们本身就是一个对象。 此模板不起作用,但是如何将其更改为生成上面所需的表格?
编辑:在这个例子中的props
是name
和lastLogin
,但我需要一个解决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 -->