Вставка информации из массива объектов со вложенным массивом объектов
На основании ответа сервера мне нужно выводить на страницу некоторые элементы. Проблема в том, что ответ является массивом объектов со вложенным массивом объектов, и я не знаю, у меня не получается вот на втором уровне массива объектов вытаскивать необходимую информацию так, чтобы по итогу у меня не дублировались элементы при вставке в документ.
const resultsBlock = document.getElementById('results');
let resp = [{
"_id": "63a0df907e9b89f949096c72",
"pdf_file_id": "63a0df8f53baa85ee0096638",
"title": "sample.pdf",
"updated_at": "2022-12-19 22:02:57",
"tags": [{
"title": "1",
"color": "purple",
"updated_at": "2023-01-20 08:47:07",
"created_at": "2023-01-20 08:47:07",
"_id": "63ca550bdcc60c139b0eec5b"
}, {
"title": "8",
"color": "red",
"updated_at": "2023-01-20 08:48:09",
"created_at": "2023-01-20 08:48:09",
"_id": "63ca5549e8b09bcb6708dab3"
}],
"pdf_file": {
"_id": "63a0df8f53baa85ee0096638",
"images": {"small": "thumbnails\/5245c582a3f9981a642c32561ed906d2.png"}
},
"pdf_sharing": null,
"link_to_sign": null,
"link_to_fill": null
}, {
"_id": "63b520654edf85b79002f992",
"pdf_file_id": "63b52064b8be365fdd072c16",
"title": "33557-001.pdf",
"updated_at": "2023-01-11 07:46:03",
"tags": [{
"title": "3",
"color": "grey",
"updated_at": "2023-01-20 08:47:54",
"created_at": "2023-01-20 08:47:54",
"_id": "63ca553ae8b09bcb6708dab2"
}, {
"title": "5",
"color": "yellow",
"updated_at": "2023-01-20 08:47:59",
"created_at": "2023-01-20 08:47:59",
"_id": "63ca553f3363b2065f0cbe31"
}],
"pdf_file": {
"_id": "63b52064b8be365fdd072c16",
"images": {"small": "thumbnails\/0c4323c3c623563bd2ad016b86e9f2fc.png"}
},
"pdf_sharing": null,
"link_to_sign": null,
"link_to_fill": null
}]
/* перебор ответа сервера */
function responseIteration() {
const responseData = resp.map(item => {
const docID = item._id,
docTitle = item.title;
const innerValues = Object.values(item.tags);
/* перебор для вложенного массива объектов с тегами */
return innerValues.map(subItem => {
const tagID = subItem._id,
tagColor = subItem.color;
/* разметка вставляемого документа */
let documentMarkup = {
'markup': `<div class="document-item" data-id="${docID}">
<a class="title">${docTitle}</a>
<ul class="tags-list">
<li><span class="item ${tagColor}"></span></li>
</ul>
</div>`
}
/* непосредственно вставка */
resultsBlock.insertAdjacentHTML('afterbegin', documentMarkup.markup);
});
});
}
responseIteration();
ul {
margin: 0;
padding: 0;
list-style: none;
}
.item {
display: inline-flex;
width: 15px;
height: 15px;
}
.grey {
background: #d3d3d3;
}
.yellow {
background: yellow;
}
.purple {
background: purple;
}
.red {
background: red;
}
<div id="results"></div>
В моём коде я понимаю что ошибка в том, что insertAdjacentHTML выполняется уже при переборе tags, но если вынести его на уровень первого перебора, тогда информация из tags недоступна.
Песочница здесь.
Ответы (2 шт):
Потому что Вам сначала необходимо перебрать тэги в эелементе, аккумулировать элементы списка, а потом вставлять в родительский элемент.
По коду заменил map на forEach, потому что вы ничего не возвращаете из map. А reduce просто для удобства, чтобы сразу строку вернуть. Хотя можете использовать map().join('') вместо этого. На алгоритм самой задачи не влияет.
const resultsBlock = document.getElementById('results');
let resp = [{
"_id": "63a0df907e9b89f949096c72",
"pdf_file_id": "63a0df8f53baa85ee0096638",
"title": "sample.pdf",
"updated_at": "2022-12-19 22:02:57",
"tags": [{
"title": "1",
"color": "purple",
"updated_at": "2023-01-20 08:47:07",
"created_at": "2023-01-20 08:47:07",
"_id": "63ca550bdcc60c139b0eec5b"
}, {
"title": "8",
"color": "red",
"updated_at": "2023-01-20 08:48:09",
"created_at": "2023-01-20 08:48:09",
"_id": "63ca5549e8b09bcb6708dab3"
}],
"pdf_file": {
"_id": "63a0df8f53baa85ee0096638",
"images": {"small": "thumbnails\/5245c582a3f9981a642c32561ed906d2.png"}
},
"pdf_sharing": null,
"link_to_sign": null,
"link_to_fill": null
}, {
"_id": "63b520654edf85b79002f992",
"pdf_file_id": "63b52064b8be365fdd072c16",
"title": "33557-001.pdf",
"updated_at": "2023-01-11 07:46:03",
"tags": [{
"title": "3",
"color": "grey",
"updated_at": "2023-01-20 08:47:54",
"created_at": "2023-01-20 08:47:54",
"_id": "63ca553ae8b09bcb6708dab2"
}, {
"title": "5",
"color": "yellow",
"updated_at": "2023-01-20 08:47:59",
"created_at": "2023-01-20 08:47:59",
"_id": "63ca553f3363b2065f0cbe31"
}],
"pdf_file": {
"_id": "63b52064b8be365fdd072c16",
"images": {"small": "thumbnails\/0c4323c3c623563bd2ad016b86e9f2fc.png"}
},
"pdf_sharing": null,
"link_to_sign": null,
"link_to_fill": null
}]
/* перебор ответа сервера */
function responseIteration() {
resp.forEach(item => {
const docID = item._id,
docTitle = item.title;
/* перебор для вложенного массива объектов с тегами */
let tags = item.tags.reduce((acc,tag) => {
const tagID = tag._id,
tagColor = tag.color;
acc += `<li><span class="item ${tagColor}"></span></li>`;
return acc;
},'');
//вставляем тэги в список
let documentMarkup = `<div class="document-item" data-id="${docID}">
<a class="title">${docTitle}</a>
<ul class="tags-list">
${tags}
</ul>
</div>`
resultsBlock.insertAdjacentHTML('afterbegin', documentMarkup);
});
}
responseIteration();
ul {
margin: 0;
padding: 0;
list-style: none;
}
.item {
display: inline-flex;
width: 15px;
height: 15px;
}
.grey {
background: #d3d3d3;
}
.yellow {
background: yellow;
}
.purple {
background: purple;
}
.red {
background: red;
}
<div id="results"></div>
Дело в том что в переменной documentMarkup вы уже в вёрстку заложили что должен быть всего один li. Значит нам надо отдельно собрать вместе все нужные нам li и только потом вставить в вёрстку
Для удобства и лучше читабельности создал 2 функции: li и documentItem. Далее просто проходимся по массиву с помощью forEach. А вот map используется чтобы вернуть видоизменённый массив, но вы просто перебираете массив, потому лучше использовать обычный for, for..of или forEach. Далее с помощью reduce проходимся по всем тегам и собираем их вместе
const resultsBlock = document.querySelector('#results');
const results = [{
"_id": "63a0df907e9b89f949096c72",
"pdf_file_id": "63a0df8f53baa85ee0096638",
"title": "sample.pdf",
"updated_at": "2022-12-19 22:02:57",
"tags": [{
"title": "1",
"color": "purple",
"updated_at": "2023-01-20 08:47:07",
"created_at": "2023-01-20 08:47:07",
"_id": "63ca550bdcc60c139b0eec5b"
}, {
"title": "8",
"color": "red",
"updated_at": "2023-01-20 08:48:09",
"created_at": "2023-01-20 08:48:09",
"_id": "63ca5549e8b09bcb6708dab3"
}],
"pdf_file": {
"_id": "63a0df8f53baa85ee0096638",
"images": {"small": "thumbnails\/5245c582a3f9981a642c32561ed906d2.png"}
},
"pdf_sharing": null,
"link_to_sign": null,
"link_to_fill": null
}, {
"_id": "63b520654edf85b79002f992",
"pdf_file_id": "63b52064b8be365fdd072c16",
"title": "33557-001.pdf",
"updated_at": "2023-01-11 07:46:03",
"tags": [{
"title": "3",
"color": "grey",
"updated_at": "2023-01-20 08:47:54",
"created_at": "2023-01-20 08:47:54",
"_id": "63ca553ae8b09bcb6708dab2"
}, {
"title": "5",
"color": "yellow",
"updated_at": "2023-01-20 08:47:59",
"created_at": "2023-01-20 08:47:59",
"_id": "63ca553f3363b2065f0cbe31"
}],
"pdf_file": {
"_id": "63b52064b8be365fdd072c16",
"images": {"small": "thumbnails\/0c4323c3c623563bd2ad016b86e9f2fc.png"}
},
"pdf_sharing": null,
"link_to_sign": null,
"link_to_fill": null
}];
function responseIteration() {
const li = (color) => `<li><span class="item ${color}"></span></li>`;
const documentItem = (id, title, tagsList) => `
<div class="document-item" data-id="${id}">
<a class="title">${title}</a>
<ul class="tags-list">
${tagsList}
</ul>
</div>
`;
results.forEach(result => {
const id = result._id;
const title = result.title;
const tagsList = result.tags.reduce((lis, tag) => lis + li(tag.color), '');
resultsBlock.insertAdjacentHTML('afterbegin', documentItem(id, title, tagsList));
});
}
responseIteration();
ul {
margin: 0;
padding: 0;
list-style: none;
}
.item {
display: inline-flex;
width: 15px;
height: 15px;
}
.grey {
background: #d3d3d3;
}
.yellow {
background: yellow;
}
.purple {
background: purple;
}
.red {
background: red;
}
<div id="results"></div>