Crearea dinamica a tabelelor HTML
Folosim WebAPI pentru crearea tabelelor HTML
HTMLTableElements
Fara alte unelte la indemana (librarii externe), vom crea dinamic un tabel HTML folosind Web API (plain vanilla javascript). Pentru a manipula tabelul in DOM apelam la interfata HTMLTableElement .
HTMLTableElement
->
HTMLElement
->
Element
->
Node
Crearea dinamica pornind de la un set de date
Consideram urmatorul array de produse:
let products = [
{ id: 1, name: 'Product One', category: 10, price: 7 },
{ id: 2, name: 'Product Two', category: 10, price: 3 },
{ id: 3, name: 'Product Three', category: 20, price: 12 },
{ id: 4, name: 'Product Four', category: 10, price: 9 },
{ id: 5, name: 'Product Five', category: 20, price: 1 },
{ id: 6, name: 'Product Six', category: 20, price: 9 },
{ id: 7, name: 'Product Seven', category: 30, price: 21 },
{ id: 8, name: 'Product Eight', category: 20, price: 16 },
{ id: 9, name: 'Product Nine', category: 40, price: 6 },
{ id: 10, name: 'Product Ten', category: 40, price: 5 }
];
Vrem ca, pornind de la datele de mai sus, sa obtinem un tabel de forma:
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>category</th>
<th>price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Product One</td>
<td>10</td>
<td>7</td>
</tr>
<tr>
...
</tr>
...
</tbody>
</table>
Tabelul are doua sectiuni mari: thead
si tbody
. Nu folosim tfooter
.
Fiecare dintre aceste sectiuni contin randuri (tr
). Pentru zona thead
avem header in interiorul randului (th
) iar pentru continut (tbody
) avem date (td
).
Acum ca am stabilit structura, mergem mai departe cu analiza API-ului pus la dispozitie de JavaScript.
HTMLTableElement API
JavaScript ne pune la dispozitie un API dedicat pentru crearea si manipularea tabelelor in DOM. Nu e singurul mod prin care putem sa cream un tabel in pagina HTML.
Am putea sa folosim metoda generica document.createElement()
careia ii putem specifica ce nod vrem sa cream (thead
, tr
, etc.). Insa va fi mai usor daca folosim un API dedicat pentru tabel (o vom folosi totusi pentru a crea elementul table
).
Sa vedem cateva metode ale interfetei HTMLTableElement
:
-
HTMLTableElement.createTHead() - returneaza elementul
thead
gasit care este copil al tabelului iar daca nu il gaseste il creaza. -
HTMLTableElement.deleteTHead() - sterge
thead
-ul copil al elementului (table
) -
HTMLTableElement.insertRow() - returneaza un
HTMLTableRowElement
(randul nou din tabel). Daca este nevoie creaza sitbody
. Ii putem specifica un index iar noul rand va fi introdus pe pozitia imediat anterioara acestui index.
Nu este nevoie sa utilizam
append
asa cum ar fi fost nevoie cu metodadocument.createElement()
. Deasemenea multe linii de cod se economisesc prin crearea automata a luitbody
sauthead
.
- HTMLTableElement.deleteRow() - sterge un rand din colectie. Va sterge randul de la indexul specificat. Putem trimite ca index valoarea
-1
pentru a sterge ultimul rand.
HTMLTableRowElement API
Am vazut mai sus ca prin utilizarea metodei insertRow()
se creaza un element de tipul
HTMLTableRowElement
.
HTMLTableRowElement
->
HTMLElement
->
Element
->
Node
Sa vedem cele doua metode specifice puse la dispozitie pe un element de acest tip:
-
HTMLTableRowElement.deleteCell() - elimina o celula de la pozitia indexului trimis ca parametru.
-
HTMLTableRowElement.insertCell() - adauga o celula chiar inainte de pozitia specificata ca parametru. Daca nu trimitem parametru (sau trimitem
-1
) atunci se adauga la finalul randului.
Atat HTMLTableElement
cat si HTMLTableRowElement
au cateva proprietati ce ne pot fi utile, de exemplu:
HTMLTableElement.tHead
, HTMLTableElement.rows
(read-only), HTMLTableElement.tBodies
(read-only)
Da, pot exista mai multe body-uri intr-un tabel.
HTMLTableRowElement.rowIndex
, HTMLTableRowElement.cells
ambele sunt read-only
Sa facem _setup_-ul pentru noul proiect
Fisierul HTML:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic HTML Table</title>
</head>
<body>
<main></main>
<script src="app.js"></script>
</body>
</html>
Codul JS il vom scrie in fisierul app.js
. Pentru inceput cream dinamic un nod <table>
// app.js
let products = [
{ id: 1, name: 'Product One', category: 10, price: 7 },
...
];
window.onload = function(){
let body = document.querySelector('main');
let table = document.createElement('table');
body.appendChild(table);
}
Daca inspectam acum pagina HTML vom gasi un nou element <table>
adaugat in interiorul lui <main>
:
<main>
<table></table>
</main>
table-utils.js
Vom crea o mini librarie reutilizabila pentru crearea dinamica a tabelelor.
// table-utils.js
const TUtils = (function(){ // IIFE - vom avea un singur obiect global cu toate metodele
function createTHead(table, headData) {
debugger
let thead = table.createTHead();
let hrow = thead.insertRow(); // fara sa fie nevoie de appendChild
for (let prop in headData) { // pentru fiecare proprietate a obiectului
let th = document.createElement("th");
let text = document.createTextNode(prop); // head-ul coloanelor
th.appendChild(text); // aici este gata elementul th
hrow.appendChild(th); // <tr> <th>id</th> </tr>
}
}
return {
createTHead
}
}())
Nu uitam sa o incarcam in pagina index.html
:
<!-- index.html -->
...
<body>
<main></main>
<script src="table-utils.js"></script>
<script src="app.js"></script>
</body>
</html>
Utilizam prima varianta a mini librariei:
// app.js
...
window.onload = function(){
...
body.appendChild(table);
// cream header-ul pentru tabela
TUtils.createTHead(table, products[0]);
}
- am trimis primul obiect din array ca parametru, libraria va utiliza denumirile proprietatilor pentru a genera
thead
-ul tabelului.
Verificam rezultatul in browser. Ar trebui sa vedem tabelul fara date dar cu header. Codul HTML generat este:
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>category</th>
<th>price</th>
</tr>
</thead>
</table>
Acum sa adaugam datele in tabel:
// table-utils.js
const TUtils = (function(){ // IIFE - vom avea un singur obiect global cu toate metodele
...
function addTRows(table, tableData) {
for (let item of tableData) {
let drow = table.insertRow();
// iteram asupra proprietatilor din fiecare obiect pentru a crea coloanele (cells)
for (prop in item) {
let dcell = drow.insertCell();
let text = document.createTextNode(item[prop]);
dcell.appendChild(text); // <td>Product One</td>
}
// acum randul este gata
// <tr> <td>1</td> <td>Product One</td> <td>10</td> <td>7</td> </tr>
}
}
return {
createTHead,
addTRows
}
}())
Acum sa trimitem datele pentru crearea randurilor in tabel:
// app.js
window.onload = function(){
...
// incepem prin a adauga randurile de date pentru a crea `tbody`ea
// daca rulam crearea thead-ului prima data, toate datele se adauga la thd
TUtils.addTRows(table, products);
TUtils.createTHead(table, products[0]);
}
Aici conteaza ordinea in care rulam cele doua functii addTRows
si createTHead
. Asa cum este acum, totul este in regula, avem cele doua sectiuni thead
si tbody
, fiecare cu randurile specifice fiecarei sectiuni.
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>category</th>
<th>price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Product One</td>
<td>10</td>
<td>7</td>
</tr>
...
</tbody>
</table>
Daca am modifica ordinea de executie a celor doua functii
// app.js
...
TUtils.createTHead(table, products[0]);
TUtils.addTRows(table, products);
...
atunci HTML-ul generat ar arata ca mai jos:
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>category</th>
<th>price</th>
</tr>
<tr>
<td>1</td>
<td>Product One</td>
<td>10</td>
<td>7</td>
</tr>
...
</thead>
</table>
Lipseste tbody
. O solutie ar fi sa cream manual nodul tbody
, sa-i luam referinta sa folosim insertCell
de pe tbody
:
let drow = table.querySelector('tbody').insertRow();
Insa este mai usor sa punem intai datele, pentru ca in acest fel tbody
va fi creat automat pentru noi.
De ce nu functioneaza corect acum? JavaScript gaseste deja elementul row
din thead
cand incepe sa adauge randurile de date si va folosi parintele randului existent (randul din thead
) ca sa adauge celelalte randuri. Considera ca nu este nevoie sa creeze sectiune noua pentru tbody
.
Nu avem o metoda createTBody
ca sa obtinem o referinta la care sa adaugam randurile de date, in schimb avem metoda createTHead
si atunci vom simplifica codul nostru daca prima data adaugam datele (primim gratis un tbody
).
Sumar
Am creat dinamic un tabel in pagina folosind Web API. Am vazut ca putem simplifica foarte mult codul folosind API-ul dedicat pentru tabele: HTMLTableElement si HTMLTableRowElement
Am minimizat utilizarea metodei generice de creare a elementelor HTML document.createElement()
si in felul asta si codul este mai simplu.
Libraria table-utils.js
poate fi imbunatatita si poate fi chiar extinsa cu implementarea interactivitatii cu utilizatorul: sortare, filtrare, etc.
Share this post
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email