如何使用敲除来遍历物体(未数组)(How to use knockout to iterate ov

2019-07-19 19:06发布

我想用类似淘汰赛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在这个例子中是namelastLogin ,但我需要一个解决方案,是不可知的什么是包含内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>

Answer 1:

你总是可以创建绑定处理程序来处理的转变。

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>


Answer 2:

在现代浏览器(或用适当的填充工具),你可以遍历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>

拨弄 。

注:我只是好奇,想看看这是否会工作,模板身体上面比想什么,我在生产中使用(或回来几个月后,成为像“跆拳道”)污染更严重。

自定义绑定将是一个更好的选择,我个人的喜好,虽然是使用一个计算观察到或计算观察到可写 (与工作时,后者将方便json响应一拉宁静API)。



Answer 3:

这是杰夫的回答的修改,以保留的结合上下文

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> 


Answer 4:

<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);

希望这是有帮助的(原谅简洁)

附录:

这里有一个工作例子已经测试...

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


Answer 5:

据说,有一个更深层次的问题( 见这个线程在谷歌组 ),其是的foreach把对象作为参数的字典,而不是作为集合进行迭代。

我最好的解决办法,到目前为止是综合foreachObject.keys(myobject)和“用”结合上下文。



Answer 6:

简化的答案与任何基本对象的工作,为我工作:

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


Answer 7:

(不严格遍历性,但创建上表)

<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/



Answer 8:

我有点晚了,但我认为这应该工作,一个简单的解决方案,而无需使用任何模板。

 var json = [ { "PortfolioCompanyId":240, "dt":"2018-12-31 00:00:00.0", "ValuationDate":"2017-09-30 00:00:00.0", "capitalexpenditure":-5555660.0, "workingcapitalchange":-812350.0 }, { "PortfolioCompanyId":240, "dt":"2019-12-31 00:00:00.0", "ValuationDate":"2017-09-30 00:00:00.0", "capitalexpenditure":-5613520.0, "workingcapitalchange":-893530.0 }, { "PortfolioCompanyId":240, "dt":"2020-12-31 00:00:00.0", "ValuationDate":"2017-09-30 00:00:00.0", "capitalexpenditure":-5674130.0, "workingcapitalchange":-982850.0 }, { "PortfolioCompanyId":240, "dt":"2021-12-31 00:00:00.0", "ValuationDate":"2017-09-30 00:00:00.0", "capitalexpenditure":-6241543.0, "workingcapitalchange":-1081135.0 }, { "PortfolioCompanyId":240, "dt":"2022-12-31 00:00:00.0", "ValuationDate":"2017-09-30 00:00:00.0", "capitalexpenditure":-6865697.3, "workingcapitalchange":-1189248.5 } ]; var DataModel = function () { this.jsonArray = ko.observable(json); }; ko.applyBindings(new DataModel()); 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <table class="table" data-bind="foreach:jsonArray"> <tr data-bind="foreach:Object.keys($data)"> <!-- JSON Object --> <td data-bind="text : $parent[$data]"></td> </tr> </table> 



文章来源: How to use knockout to iterate over an object (not array)