使用knockout.js将嵌套的JSON显示为嵌套列表

时间:2022-03-20 14:31:22

I have a nested JSON like this:

我有一个像这样的嵌套JSON:

[
    {
        "Run 1": {
            "1.2.0": {
                "Server": {
                    "TestSuite 1": [
                        {
                            "version": "1.2.0",
                            "type": "server",
                            "testdef": "TestSuite 1",
                            "testcaseid": "TestCase 1",
                            "status": "pass"
                        },
                        {
                            "version": "1.2.0",
                            "type": "server",
                            "testdef": "TestSuite 1",
                            "testcaseid": "TestCase 2",
                            "status": "fail"
                        }
                    ],
                    "TestSuite 2": [
                        {
                            "version": "1.2.0",
                            "type": "server",
                            "testdef": "TestSuite 2",
                            "testcaseid": "TestCase 1",
                            "status": "pass"
                        }
                    ]
                }
            }
        }
    }
]

I want to display it on the html page as an unordered list like this: 使用knockout.js将嵌套的JSON显示为嵌套列表

我想在html页面上显示为无序列表,如下所示:

but I am seeing the last item repeated multiple times:

但我看到最后一项重复多次:

使用knockout.js将嵌套的JSON显示为嵌套列表

This is html with knockout.js bindings:

这是带有knockout.js绑定的html:

<div class="row">
  <div class="tree">
    <ul data-bind="foreach: {data: testResults, as: 'item'}">
      <li data-bind="foreach: {data: Object.keys(item), as: 'key'}"><span data-bind="text: 'Run' + key"></span>
        <ul data-bind="foreach: {data: item[key], as: 'item2'}" class="child">
          <li data-bind="foreach: {data: Object.keys(item2), as: 'key2'}"><span data-bind="text: key2"> </span>
            <ul data-bind="foreach: {data: item2[key2], as: 'item3'}" class="child">
              <li data-bind="foreach: {data: Object.keys(item3), as: 'key3'}"><span data-bind="text: key3"> </span>
                <ul data-bind="foreach: {data: item3[key3], as: 'item4'}" class="child">
                  <li data-bind="foreach: {data: Object.keys(item4), as: 'key4'}"><span data-bind="text: key4"> </span>
                    <ul data-bind="foreach: {data: item4[key4], as: 'item5'}" class="child">
                      <li data-bind="foreach: {data: Object.keys(item5), as: 'key5'}"><span data-bind="text: item5.testcaseid, css : {'bg-success' : item5.status == 'pass', 'bg-danger' : item5.status == 'fail'}"> </span><br></li>
                    </ul>
                  </li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</div>

testResults is a ko.observableArray() in my view model which contains the above JSON.

testResults是我的视图模型中的ko.observableArray(),它包含上面的JSON。

What would be the correct way to display the leaf elements only once

仅显示叶元素一次的正确方法是什么

1 个解决方案

#1


1  

The problem is you're nesting so many foreach bindings that you're getting lost in how many nested loops there are. Your last look at the very end is not needed. You loop through the keys of the test suite objects when you don't need to. Remove that last foreach binding.

问题是你正在嵌套这么多的foreach绑定,你会丢失多少嵌套循环。不需要你最后一次看。当您不需要时,可以遍历测试套件对象的键。删除最后一个foreach绑定。

<ul data-bind="foreach: {data: item4[key4], as: 'item5'}" class="child">
    <li>
        <span data-bind="text: item5.testcaseid,
                         css : {'bg-success' : item5.status == 'pass',
                                'bg-danger' : item5.status == 'fail'}">
        </span><br>
    </li>
</ul>

Don't do this. Do you really want to have to look at that view and try to maintain that?

不要这样做。你真的想看看那个观点并尝试保持这种观点吗?

I have two suggestions, either map the results out to arrays and foreach over those or iterate over the properties alone with the help of custom bindings to make it more manageable. You can use this foreachprop binding handler to do this:

我有两个建议,要么将结果映射到数组,也要预先对结果进行映射,或者在自定义绑定的帮助下单独迭代属性,以使其更易于管理。您可以使用此foreachprop绑定处理程序执行此操作:

<ul data-bind="foreach: testResults">
    <li data-bind="foreachprop: $data"><span data-bind="text: key"></span>
        <ul data-bind="foreachprop: value">
            <li><span data-bind="text: key"></span>
                <ul data-bind="foreachprop: value">
                    <li><span data-bind="text: key"></span>
                        <ul data-bind="foreachprop: value">
                            <li><span data-bind="text: key"></span>
                                <ul data-bind="foreach: value">
                                    <li><span data-bind="text: testcaseid"></span></li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

fiddle

#1


1  

The problem is you're nesting so many foreach bindings that you're getting lost in how many nested loops there are. Your last look at the very end is not needed. You loop through the keys of the test suite objects when you don't need to. Remove that last foreach binding.

问题是你正在嵌套这么多的foreach绑定,你会丢失多少嵌套循环。不需要你最后一次看。当您不需要时,可以遍历测试套件对象的键。删除最后一个foreach绑定。

<ul data-bind="foreach: {data: item4[key4], as: 'item5'}" class="child">
    <li>
        <span data-bind="text: item5.testcaseid,
                         css : {'bg-success' : item5.status == 'pass',
                                'bg-danger' : item5.status == 'fail'}">
        </span><br>
    </li>
</ul>

Don't do this. Do you really want to have to look at that view and try to maintain that?

不要这样做。你真的想看看那个观点并尝试保持这种观点吗?

I have two suggestions, either map the results out to arrays and foreach over those or iterate over the properties alone with the help of custom bindings to make it more manageable. You can use this foreachprop binding handler to do this:

我有两个建议,要么将结果映射到数组,也要预先对结果进行映射,或者在自定义绑定的帮助下单独迭代属性,以使其更易于管理。您可以使用此foreachprop绑定处理程序执行此操作:

<ul data-bind="foreach: testResults">
    <li data-bind="foreachprop: $data"><span data-bind="text: key"></span>
        <ul data-bind="foreachprop: value">
            <li><span data-bind="text: key"></span>
                <ul data-bind="foreachprop: value">
                    <li><span data-bind="text: key"></span>
                        <ul data-bind="foreachprop: value">
                            <li><span data-bind="text: key"></span>
                                <ul data-bind="foreach: value">
                                    <li><span data-bind="text: testcaseid"></span></li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

fiddle