Как добавить данные JSON в таблицу HTML

#javascript #html #json #dom #addeventlistener

#javascript #HTML #json #dom #addeventlistener

Вопрос:

В настоящее время я извлекаю данные, которые мне нужно добавить в таблицу HTML, как только я их получу.

Я пробовал несколько способов, но я не могу добавлять данные динамически после загрузки страницы.

Я хочу добавить их с помощью Javascript или jQuery

Вот структура HTML :

 <div>
    <table cellspacing="0" cellpadding="0">
        <thead>
          <tr>
            <th scope="col"><span>Email</span></th>
            <th><span>Last Name</span></th>
            <th><span>First Name</span></th>
            <th><span>Role</span></th>
            <th><span>Cell Phone User</span></th>
          </tr>
        </thead>
           <tbody>
              <tr>
                 <td scope="row" data-label="Email"></td>
                 <td data-label="Last Name"></td>
                 <td data-label="First Name"></td>
                 <td data-label="Role"></td>
                 <td data-label="Cell Phone User"></td>
               </tr>
           </tbody> 
    </table>
</div>
  

Вот пример того, как данные выглядят после их извлечения:

 [{
    "id": 1,
    "email": "janedoe@example.com",
    "familyName": "Doe",
    "givenName": "Jane",
    "role": "admin",
    "smsUser": true
  },
  {
    "id": 2,
    "email": "johndoe@example.com",
    "familyName": "Doe",
    "givenName": "John",
    "role": "standard",
    "smsUser": false
  }]

  

Вот что я пробовал до сих пор :

это мой прослушиватель событий для загрузки данных после загрузки страницы:

 
window.path = "http://localhost:3000/users";

// getUsers function plus any additional functions go here ...
const getUsers = options => {
  let url = new URL(window.path);
  if (options) {
    url.search = new URLSearchParams(options)
  }
  return Promise.resolve(fetch(url))
}

document.addEventListener('DOMContentLoaded', () => {

 /* SELECT DOM ELEMENTS*/ 
let table = document.querySelector('tbody');

let promise = getUsers({page=2, role:'admin'})

.then(data => {

var html = '<table>';
for( var j in data[0] ) {
    html  = '<th>'   j   '</th>';
 }
     html  = '</tr>';

     for( var i = 0; i < data.length; i  ) {
      html  = '<tr>';
      for( var j in data[i] ) {
        html  = '<td>'   data[i][j]   '</td>';
      }
     }
     html  = '</table>';
     table.appendChild(html)

    return table;
  })
.catch(err => {
    console.log('Error fetching from /users', err);
    return null
  })

})



  

Приветствуется любая помощь.

Комментарии:

1. используйте jQuery, это очень просто, вы можете найти документацию и примеры по этой ссылке https://datatables.net/examples/data_sources/dom.html

2. Почему ваша html переменная string начинается с '<table>' , если вы используете querySelector для получения <tbody> тега элемента? Если table это ссылка на <tbody> , то table.append должна быть указана строка типа <tr><td>...</td></tr>

Ответ №1:

Первая проблема заключается в том, что строка

 let promise = getUsers({page=2, role:'admin'})
  

должно быть

 let promise = getUsers({page:2, role:'admin'})
  

Во-вторых, appendChild принимает не строку, а элемент DOM. В этом случае вместо этого используйте innerHTML.

В-третьих, вы используете querySelect для поиска '<tbody>' элемента, поэтому начните построение внутренних html-тегов с '<tr>' не '<table>'

 const getUsers = async options => ([
  {
    id: 1,
    email: "janedoe@example.com",
    familyName: "Doe",
    givenName: "Jane",
    role: "admin",
    smsUser: true
  },
  {
    id: 2,
    email: "johndoe@example.com",
    familyName: "Doe",
    givenName: "John",
    role: "standard",
    smsUser: false
  }
]);
  
document.addEventListener('DOMContentLoaded', async () => {
  const table = document.querySelector('tbody');
  const users = await getUsers({ page:2, role:'admin' });
  const userToTableRow = user => [
  { attrs: 'scope="row" data-label="Email"', propName: 'email'},
  { attrs: 'data-label="Last Name"', propName: 'familyName'},
  { attrs: 'data-label="First Name"', propName: 'givenName'},
  { attrs: 'data-label="Role Name"', propName: 'role'},
  { attrs: 'data-label="Cell Phone User"', propName: 'smsUser'},
  ].map(mapper => (
    `<td ${mapper.attrs}>${user[mapper.propName]}</td>`
  )).join('');
  
  const html = users.map(user =>
    `<tr>${userToTableRow(user)}</tr>`
  ).join('');
  table.innerHTML = html;
});  
 <div>
  <table cellspacing="0" cellpadding="0">
    <thead>
      <tr>
        <th scope="col"><span>Email</span></th>
        <th><span>Last Name</span></th>
        <th><span>First Name</span></th>
        <th><span>Role</span></th>
        <th><span>Cell Phone User</span></th>
      </tr>
    </thead>
    <tbody>
    </tbody> 
  </table>
</div>  

РЕДАКТИРОВАТЬ: мне нравится async / await в первой реализации выше. async это просто короткий способ заставить функцию обернуть возврат в обещание. await это просто новый языковой способ разрешить встроенное обещание без необходимости использования .then((res) => {...}) . await может использоваться только в async функции.

Ответы на вопросы в комментариях. Я представляю это альтернативное решение, которое:

  • Не использует async и await
  • издевается fetch вместо getusers
  • Использует document.createElement() и appendChild вместо простой настройки innerHTML содержимого.

 const getUsersUrl = 'http://localhost:3000/users';

function mockFetch(url) {
  const stubbedResponse = JSON.stringify([
    {
      id: 1,
      email: "janedoe@example.com",
      familyName: "Doe",
      givenName: "Jane",
      role: "admin",
      smsUser: true
    },
    {
      id: 2,
      email: "johndoe@example.com",
      familyName: "Doe",
      givenName: "John",
      role: "standard",
      smsUser: false
    }
  ]);

  return Promise.resolve({
    json() {
      return Promise.resolve(JSON.parse(stubbedResponse));
    }
  });
}

const getUsers = options => {
  let url = new URL(getUsersUrl);
  if (options) {
    url.search = new URLSearchParams(options)
  }
  return mockFetch(url);
}

const userToTableRow = user => {
  const tr = document.createElement('tr');
  [
    {
      attrs: {
        scope: 'row',
        'data-label': 'Email'
      },
      propName: 'email'
    },
    {
      attrs: { 'data-label': 'Last Name' },
      propName: 'familyName'
    },
    {
      attrs: { 'data-label': 'First Name' },
      propName: 'givenName'
    },
    {
      attrs: { 'data-label': 'Role Name' },
      propName: 'role'
    },
    {
      attrs: { 'data-label': 'Cell Phone User' },
      propName: 'smsUser'
    },
  ].map(mapper => {
    const td = document.createElement('td');
    for (const [attrName, attrValue] of Object.entries(mapper.attrs)) {
      td.setAttribute(attrName, attrValue);
    }
    td.appendChild(document.createTextNode(user[mapper.propName]));
    return td;
  }).forEach(td => { tr.appendChild(td); });
  return tr;
}
  
document.addEventListener('DOMContentLoaded', () => {
  const table = document.querySelector('tbody');
  getUsers({ page:2, role:'admin' })
    .then(response => response.json())
    .then(users => {
      users
        .map(user => userToTableRow(user))
        .forEach(tr => { table.appendChild(tr); });
  });
});  
 <div>
  <table cellspacing="0" cellpadding="0">
    <thead>
      <tr>
        <th scope="col"><span>Email</span></th>
        <th><span>Last Name</span></th>
        <th><span>First Name</span></th>
        <th><span>Role</span></th>
        <th><span>Cell Phone User</span></th>
      </tr>
    </thead>
    <tbody>
    </tbody> 
  </table>
</div>  

Комментарии:

1. Привет, Дуг, ты можешь объяснить изменение в функции getUsers? в настоящее время предполагается, что функция извлекает данные из локальной конечной точки, а затем возвращает json. Также я не понимаю изменения переменной promise.

2. также задан ли для функции параметр по умолчанию?

3. Ваш вопрос просто говорит о том, чего ожидать от http://localhost:3000/users конечной точки. Вместо того, чтобы пытаться реализовать эту конечную точку сервера, я просто издевался над сигнатурой … функцией, которая возвращает обещание, которое преобразуется в массив пользователей.

4. Если по умолчанию используется param, вы имеете в виду, что я игнорирую значение параметра options, тогда да. Я просто заглушаю возвращаемое значение.

5. что касается переменной promise. Вы объявили это, но никогда не использовали. Вместо async и await ключевых слов для сокращения я мог бы сделать let promise = getUsers({page:2, role:'admin'}); , за которым следует promise.then(users => {...})

Ответ №2:

С помощью jQuery это сделать очень просто.

Возьмите этот фрагмент в качестве примера, в котором используется библиотека jQuery DataTables.

 $(document).ready(function() {
    $('#example').DataTable( {
        ajax: {
          url: "https://reqres.in/api/users",
          dataSrc: "data"
        },
        columns: [
            { "data": "id" },
            { "data": "first_name" },
            { "data": "last_name" }
        ]
    } );
} );  
 <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet" />
<table id="example" class="display" style="width:100%">
    <thead>
        <tr>
            <th>Id</th>
            <th>First Name </th>
            <th>Last Name</th>
        </tr>
    </thead>
</table>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>  

Он также предоставляет различные настройки и интеграции, которые, я уверен, вы найдете полезными.