I'm creating a 'expense tracker' for practice.
That takes a name, a date, an amount, and shows it on the table. Everything is working ok.
I add an item it will have a data-id of 0, next tr data-id of 1, next 2, and next 3 so on.
BUT
for example if I have 3 <tr>
and I press the delete button and delete a row, and after that add another row data-id, it will be like this tr[data-id=1],tr[data-id=2],tr[data-id=2]]
I don't know what to do.
Please have a look at images. tr attr before deleting td --- tr attr after adding new td
PS: I'm using localStorage to store table td's and get td's from it and put it back in the table. I want to remove element that have been clicked from localStorage too. I need the tr id for that.
//
////// Add To The Table
//
const btn = document.getElementById("btn");
btn.addEventListener("click", add);
function add() {
// Select Elements
const name = document.getElementById("name").value,
date = document.getElementById("date").value,
amount = document.getElementById("amount").value,
currency = document.getElementById("selector").value;
// Check if inputs is not empty
if (
name.length <= 0 ||
date.length <= 0 ||
amount.length <= 0 ||
currency == "empty"
)
return;
// Create Table
const newTr = createTr(),
tdName = createTd(),
tdDate = createTd(),
tdAmount = createTd(),
tdBtn = createTd(),
deleteBtn = createInput();
// Set Data Attribute
const Trs = document.querySelectorAll("tbody > tr");
newTr.setAttribute("data-id", Trs.length);
tdName.setAttribute("class", "data");
tdDate.setAttribute("class", "data");
tdAmount.setAttribute("class", "data");
// Create Text Node
const varName = txtNode(name),
varDate = txtNode(date),
varAmount = txtNode(`${amount}${currency}`);
// Select Parent element for insert
const table = document.querySelector("table");
const tbody = document.querySelector("tbody");
// Creating Delete Button
deleteBtn.setAttribute("type", "button");
deleteBtn.setAttribute("value", "X");
deleteBtn.setAttribute("class", "deleteBtn");
deleteBtn.addEventListener("click", remover);
// Add Elements together
tdName.appendChild(varName);
tdDate.appendChild(varDate);
tdAmount.appendChild(varAmount);
tdBtn.appendChild(deleteBtn);
newTr.appendChild(tdName);
newTr.appendChild(tdDate);
newTr.appendChild(tdAmount);
newTr.appendChild(tdBtn);
tbody.appendChild(newTr);
// Add to the DOM
table.insertBefore(tbody, null);
// Add to the Local Storage
const storeTableTd = document.querySelectorAll("tbody > tr");
let tableItems = [];
for (let i = 0; i < storeTableTd.length; i ) {
let datas = storeTableTd[i].childNodes;
let combine = {
id: i,
name: datas[0].innerText,
date: datas[1].innerText,
amount: datas[2].innerText,
};
tableItems.push(combine);
}
localStorage.setItem(`table`, JSON.stringify(tableItems));
}
//
////// Delete All Rows
//
const clearBtn = document.getElementById("clear");
clearBtn.addEventListener("click", clear);
function clear() {
const storeTableRow = document.querySelectorAll("tbody > tr");
if (storeTableRow.length > 0) {
for (let i = 0; i < storeTableRow.length; i ) {
storeTableRow[i].remove();
}
}
localStorage.clear();
}
//
//////// Restore The Table
//
function restore() {
const storageTable = JSON.parse(localStorage.table);
for (let i = 0; i < storageTable.length; i ) {
// Create Elements
const newTr = createTr(),
createName = createTd(),
createDate = createTd(),
createAmount = createTd(),
createDeleteBtn = createTd(),
deleteBtn = createInput(),
textNodeName = txtNode(`${storageTable[i].name}`),
textNodeDate = txtNode(`${storageTable[i].date}`),
textNodeAmount = txtNode(`${storageTable[i].amount}`),
// Select Parent for Insert
selectBody = document.querySelector("tbody");
// Set Attributes
newTr.setAttribute("data-id", `${storageTable[i].id}`);
deleteBtn.setAttribute("type", "button");
deleteBtn.setAttribute("value", "X");
deleteBtn.setAttribute("class", "deleteBtn");
//TODO Add Delete and Create a Function withit
createName.appendChild(textNodeName);
createDate.appendChild(textNodeDate);
createAmount.appendChild(textNodeAmount);
createDeleteBtn.appendChild(deleteBtn);
newTr.appendChild(createName);
newTr.appendChild(createDate);
newTr.appendChild(createAmount);
newTr.appendChild(createDeleteBtn);
selectBody.insertBefore(newTr, null);
}
}
// Call Restore function
const storeTd = document.querySelectorAll("td");
if (storeTd.length == 0) {
if (localStorage.length > 0) {
restore();
}
}
// Delete Button Event Listener
let selectAllBtns = document
.querySelectorAll("input.deleteBtn")
.forEach((item) => item.addEventListener("click", remover));
function remover(e) {
// Remove From Local Storage
const searchId = parseInt(e.path[2].attributes[0].value),
storageTable = JSON.parse(localStorage.table),
newLocalStorage = storageTable.filter((obj) => obj.id !== searchId);
localStorage.setItem("table", JSON.stringify(newLocalStorage));
// Remove Selected Element
const tbody = document.querySelector("tbody"),
elementToRemove = e.path[2];
tbody.removeChild(elementToRemove);
}
//
////// Show Time and Date
//
// Select the Div
const getDateDiv = document.querySelector("div.date");
const getHourDiv = document.querySelector("div.hour");
function getDate() {
// Hour
let newDate = new Date(),
hour = newDate.getHours(),
amPm = hour > 12 ? "PM" : "AM",
tweleHourFormat = hour % 12,
minuets = newDate.getMinutes(),
seconds = newDate.getSeconds();
// Date
const year = newDate.getFullYear(),
months = newDate.getMonth() 1,
day = newDate.getDate();
// Add Zero to Mineuts and Seconds
if (minuets < 10) {
minuets = `0${minuets}`;
}
if (seconds < 10) {
seconds = `0${seconds}`;
}
// Add to the Dom
const date = `${year}/${months}/${day}`;
const time = `${tweleHourFormat}:${minuets}:${seconds} ${amPm}`;
getDateDiv.innerHTML = `${date}`;
getHourDiv.innerHTML = `${time}`;
setTimeout(getDate, 800);
}
getDate();
//
/////// Create Element Function
//
function createTd() {
return document.createElement("td");
}
function createTr() {
return document.createElement("tr");
}
function createInput() {
return document.createElement("input");
}
function txtNode(node) {
return document.createTextNode(node);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;1,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<header>
<section >
<div ></div>
<div ></div>
</section>
</header>
<main >
<section >
<h1>Expense Tracker</h1>
<h2>Add a New Item: </h2>
</section>
<section >
<div >
<label id='nameLabel'>Name:</label>
<input type="text" id="name">
</div>
<div >
<label id="dateLabel">Date:</label>
<input type="date" id="date">
<label id="amountLabel">Amount:</label>
<input type="text" id="amount">
<select id="selector" value="Rial">
<option id="choose" value="empty">Choose</option>
<option id="dollar" value="$">Dollar</option>
<option id="rial" value="﷼">Rial</option>
<option id="euro" value="€">Euro</option>
<option id="pound" value="£">Pound</option>
</select>
<div>
</section>
<div >
<input type="button" id="btn" value="Add Expense">
<input type="button" id="clear" value="Clear the List">
</div>
<table>
<thead>
<tr>
<th id="headName">Name</th>
<th id="headDate">Date</th>
<th id="headAmount">Amount</th>
<th> </th>
</tr>
<tbody></tbody>
</thead>
</table>
<div id="demo"></div>
</div>
<script src="script.js"></script>
</body>
</html>
CodePudding user response:
in remover()
function to update localStorage index
replace
newLocalStorage = storageTable.filter((obj) => obj.id !== searchId);
with
newLocalStorage = storageTable.filter((obj) => obj.id !== searchId)
.map((obj, index) => {
obj.id = index;
return obj
});
and to update elements data-id
tbody.removeChild(elementToRemove);
// add this lines
document.querySelectorAll("tbody > tr").forEach((item, index) => {
item.setAttribute("data-id", index)
})
demo on jsfiddle,