Задать вопрос
Recreator
@Recreator

Как вывести элементы массива в разные блоки по ID?

Получаю массив и пытаюсь раскидать данные по ID в разные блоки:

async function getJson() {
  const requestURL = 'https://jsonplaceholder.typicode.com/posts';
  const request = new Request(requestURL);
  const response = await fetch(request);
  const json = await response.json();
  displayData(json);
}

function displayData(json) {
  json.forEach((i) =>
    document.getElementById(`${i.id}`).insertAdjacentHTML(
      'beforeEnd',
      ` <h2>Id: ${i.id}</h2>
        <h3>${i.title}</h3>
        <p>${i.body}</p>
      `
    )
  );
}
getJson();

<section>
      <div id="1"></div>
      <div id="2"></div>
      <div id="3"></div>
      <div id="4"></div>
      <div id="5"></div>
    </section>

Странно, но все работает, несмотря на ошибку:

TypeError: Cannot read properties of null (reading 'insertAdjacentHTML').

Вопрос: а как это сделать правильно?
  • Вопрос задан
  • 125 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Странно, но все работает, несмотря на ошибку:

TypeError: Cannot read properties of null (reading 'insertAdjacentHTML').

Ничего странного, id существующих блоков совпадают с id первых объектов в массиве, т.е., сначала заполняются все существующие блоки, а уже потом случается ошибка, когда пытаетесь дёрнуть метод у отсутствующего блока.

Какие есть способы победить ошибку:

  • Проверка наличия элемента перед тем как попытаться что-то в него добавить.

    Можно делать это явно:

    arr.forEach(n => {
      const el = document.getElementById(n.id);
      if (el) {
        el.innerHTML = `
          <h2>Id: ${n.id}</h2>
          <h3>${n.title}</h3>
          <p>${n.body}</p>
        `;
      }
    });

    Или не очень:

    for (const { id, title, body } of arr) {
      document.querySelector(`[id="${id}"]`)?.insertAdjacentHTML('beforeend', `
        <h2>Id: ${id}</h2>
        <h3>${title}</h3>
        <p>${body}</p>
      `);
    }

  • Создание элементов под все полученные объекты (в этом случае пусть section изначально будет пустым):

    document.querySelector('section').innerHTML = arr
      .map(n => `
        <div id="post-${n.id}">
          <h2>Id: ${n.id}</h2>
          <h3>${n.title}</h3>
          <p>${n.body}</p>
        </div>`)
      .join('');

  • Ограничение объёма получаемых данных.

    Если id элементов действительно имеют показанный вами вид (начинаются с 1 и идут по возрастанию), то просто запрашиваем столько объектов, сколько есть элементов:

    const limit = document.querySelector('section').children.length;
    const requestURL = `https://jsonplaceholder.typicode.com/posts?_limit=${limit}`;

    Или, можно запросить объекты с id как у элементов:

    const requestURL = 'https://jsonplaceholder.typicode.com/posts?' + Array
      .from(document.querySelector('section').children, n => `id=${n.id}`)
      .join('&');


Какой из способов следует предпочесть? 2 + 3. Только, конечно, количество объектов или их id надо брать не из DOM.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
twobomb
@twobomb
Ну это же очевидно, что `${i.id}` передаёт такой id элемента, которого не существует на странице.
Оно будет работать, но какой-то элемент пропускает, или может там пустой приходит...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы