Добавление нескольких не-вложенных элементов для каждого элемента данных с 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')
но я хотел бы сохранить исходный выбор даже после добавления, поэтому я мог бы продолжать добавлять к родительскому элементу. Спасибо!
Ответы
Ответ 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)); });