Подтвердить что ты не робот

Добавление нескольких не-вложенных элементов для каждого элемента данных с D3.js

Я хотел бы создать несколько не вложенных элементов, используя d3, чтобы создать такую ​​структуру:

    <div id="parent">
        <p> from data[0] </p>
        <p> from data[0] </p>

        <p> from data[1] </p>
        <p> from data[1] </p>

        <p> from data[2] </p>
        <p> from data[2] </p>
    </div>

создание вложенных структур будет похоже на

    d3.select('#parent').selectAll('p').data(data).enter().
           append('p')...append('p')

но я хотел бы сохранить исходный выбор даже после добавления, поэтому я мог бы продолжать добавлять к родительскому элементу. Спасибо!

4b9b3361

Ответ 1

Идомный способ заключается в вложенности:

var divs = d3.select('#parent').selectAll('p').data(data).enter().append('div');

divs.append('p')
divs.append('p')

Что создает:

<div id="parent">
  <div>
    <p> from data[0] </p>
    <p> from data[0] </p>
  </div>

  <div>
    <p> from data[1] </p>
    <p> from data[1] </p>
  </div>

  <div>
    <p> from data[2] </p>
    <p> from data[2] </p>
  </div>
</div>

Если это не сработает, сохраните свой выбор и повторно добавьте:

var enterSelection = d3.select('#parent').selectAll('p').data(data).enter();

enterSelection.append('p')
enterSelection.append('p')

затем отсортируйте то, что вы добавили:

d3.select('#parent').selectAll('p').sort(function(a, b){ return a.index - b.index; })

Вам нужно добавить свойство index для каждого элемента data, который описывает порядок сортировки. Обычный i определяется только в контексте конкретного выбора, который теряется при повторном выборе.

Ответ 2

Используйте append() для первого элемента и insert() для второго. Это устраняет необходимость сортировки после этого (спасибо @scuerda за указание на это) (JSFiddle):

data = [{}, {}, {}];
var enterSelection = d3.select('#parent').selectAll('p').data(data).enter()

enterSelection.append('p').text(function(d, i) {return 'from data[' + i + ']'})
enterSelection.insert('p').text(function(d, i) {return 'from data[' + i + ']'})

Это даст вам запрошенную требуемую структуру:

<p>from data[0]</p>

<p>from data[0]</p>

<p>from data[1]</p>

<p>from data[1]</p>

<p>from data[2]</p>

<p>from data[2]</p>

Ответ 3

Вы также можете сделать это в одном цикле select/enter следующим образом

d3.select('#parent').selectAll('p').data(data).enter().
append('p').text(function(d) {return 'from data[0]')}).
select(function() { return this.parentNode; }).
append('p').text(function(d) {return 'from data[0]')});

Ответ 4

Вместо .append(),

Вы также можете обернуть функцию, которая создает новый контент в .html()

d3.select('#parent')
  .selectAll('div')
    .data(data)
  .enter()
    .append('div')
    .html(function(d) {return "<p>" + from data[0] + "<p>" etc..... ;});

Ответ 5

Как и выше, но в другой идиоме. Это вернее для подхода вложенных выборов и устраняет необходимость в сортировке или вставке:

var divs = d3.select('#parent');

var ps = divs.selectAll('#parent > div')
    .data(d3.range(3)).enter().append('div');

ps.append('p').html(function(d,i) { return 'from data[' + i + ']'; });
ps.append('p').html(function(d,i) { return 'from data[' + i + ']'; });

Более элегантно (и, вероятно, быстрее):

var divs = d3.select('#parent');

  var ps = divs.selectAll('#parent > div')
    .data(d3.range(3)).enter().append('div');

    ps.append('p').html(function(d,i) { return 'from data[' + i + ']'; })
    .select(function() { return this.parentNode.appendChild(this.cloneNode(true)); });