Отображение вложенного JSON в виде вложенного списка с использованием Knockout.js

У меня есть вложенный 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"
                        }
                    ]
                }
            }
        }
    }
]

Я хочу отобразить его на странице html в виде неупорядоченного списка, например: Маркированный список

но я вижу, что последний элемент повторяется несколько раз:

введите здесь описание изображения

Это html с привязками Knockout.js:

<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 — это ko.observableArray() в моей модели представления, которая содержит указанный выше JSON.

Каким будет правильный способ отображения элементов листа только один раз?


person Bharat    schedule 11.03.2015    source источник


Ответы (1)


Проблема в том, что вы вкладываете так много привязок 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>

Не делай этого. Вы действительно хотите смотреть на это представление и пытаться поддерживать его?

У меня есть два предложения: либо сопоставить результаты с массивами и выполнить foreach по ним, либо выполнить итерацию только по свойствам с помощью пользовательских привязок, чтобы сделать их более управляемыми. Вы можете использовать этот обработчик привязки 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>

скрипка

person Jeff Mercado    schedule 11.03.2015
comment
Спасибо. Это решение работает для того, чего я пытаюсь достичь. Я прочитаю ваш другой ответ и пойму, как создается пользовательская привязка. Что касается другого вашего предложения, отображающего приведенный выше JSON в массивы, это будут вложенные массивы вместо вложенных словарей, верно? - person Bharat; 12.03.2015
comment
Что ж, я имел в виду, по сути, сопоставление, выполненное в обработчике привязки foreachprop. Каждый словарь будет преобразован в массив пар ключ/значение. Суть в том, чтобы преобразовать его во что-то, что можно обрабатывать изначально, чтобы вы не добавляли эту сложность в свои представления. - person Jeff Mercado; 12.03.2015