I've made a budgeting app that has expenses and Income tabs. Every time you add an expense or income, the app pushes the information inside of an array of objects and dynamically renders an <li>
component and places it inside of a <ul>
. I'm having trouble with the edit and delete features. Each individual <li>
comes with a delete and edit button. The <li>
, delete button, and edit button all have the same id of Date.now()
. Date.now() is used because it produces a number based on milliseconds and won't produce the same id twice unless someone types an expense or income twice within one millisecond I want to click on the delete button inside of the <li>
and have my app remove that individual object from my entry_list[]
array and also remove the <li>
from the DOM.
'use strict'
const balanceElement = document.querySelector(".balance .value");
const totalIncome = document.querySelector(".income-total");
const totalOutcome = document.querySelector(".outcome-total");
const incomeElement = document.querySelector(".income-tab");
const expense = document.querySelector(".expense-tab");
const all = document.querySelector(".all-tab");
const incomeList = document.querySelector(".income-tab .list");
const expenseList = document.querySelector(".expense-tab .list");
const allList = document.querySelector(".all-tab .list");
const expensesButton = document.querySelector(".tab1");
const incomeButton = document.querySelector(".tab2");
const allButton = document.querySelector(".tab3");
const addExpense = document.querySelector(".add-expense")
const expenseTitle = document.querySelector(".expense-title-input")
const expenseAmount = document.querySelector(".expense-amount-input")
const addIncome = document.querySelector(".add-income")
const incomeTitle = document.querySelector(".income-title-input")
const incomeAmount = document.querySelector(".income-amount-input")
const list = document.querySelector('.list')
//SWITCHING BETWEEN TABS
expensesButton.addEventListener('click', () => {
expense.classList.remove('hidden');
incomeElement.classList.add('hidden');
expensesButton.classList.add('clicked');
incomeButton.classList.remove('clicked');
})
incomeButton.addEventListener('click', () => {
incomeElement.classList.remove('hidden');
expense.classList.add('hidden');
expensesButton.classList.remove('clicked');
incomeButton.classList.add('clicked');
})
incomeList.addEventListener('click', deleteOrEdit)
expenseList.addEventListener('click', deleteOrEdit)
let entry_list = []
addExpense.addEventListener('click', () =>{
if(expenseTitle.value == '' || expenseAmount.value == ''){
return;
}
let expense = {
type: 'expense',
title: expenseTitle.value,
amount: expenseAmount.value,
id: Date.now()
}
entry_list.push(expense)
clearExpense()
changeLists()
})
addIncome.addEventListener('click', () =>{
if(incomeTitle.value == '' || incomeAmount.value == ''){
return;
}
let income = {
type: 'income',
title: incomeTitle.value,
amount: incomeAmount.value,
id: Date.now()
}
entry_list.push(income)
clearIncome()
changeLists()
})
const clearExpense = () =>{
expenseTitle.value = '';
expenseAmount.value = '';
}
const clearIncome = () =>{
incomeTitle.value = ''
incomeAmount.value = ''
}
const changeLists = () =>{
expenseList.innerHTML = ''
incomeList.innerHTML = ''
entry_list.map((entry) =>{
if(entry.type == 'expense'){
return expenseList.innerHTML += `<li id = "${entry.id}" class= "${entry.type}">
<div class = "entry">${entry.title}: $${entry.amount}</div>
<div class="icon-container">
<div class = "edit" id="${entry.id}"></div>
<div class ="delete" id="${entry.id}"></div>
</div>
</li>`
}
else if(entry.type == 'income'){
return incomeList.innerHTML += `<li id = "${entry.id}" class= "${entry.type}">
<div class = "entry">${entry.title}: $${entry.amount}</div>
<div class="icon-container">
<div class = "edit" id="${entry.id}"></div>
<div class ="delete" id="${entry.id}"></div>
</div>
</li>`
}
})
addIncomes()
}
const addIncomes = () =>{
let sum = 0;
let income = 0;
let outcome = 0;
balanceElement.innerHTML = 0
totalIncome.innerHTML = 0
totalOutcome.innerHTML = 0
entry_list.forEach(list =>{
if(list.type == 'expense'){
sum -= list.amount
outcome -= list.amount
}else if(list.type == 'income'){
sum += Number(list.amount)
income += Number(list.amount)
}
balanceElement.innerHTML = '$' + sum
totalIncome.innerHTML = '$' + income
totalOutcome.innerHTML = '$' + outcome
})
}
// // DETERMINE IF BUTTON IS EDIT OR DELETE
function deleteOrEdit(e){
const targetButton = e.target;
const entry = targetButton.parentNode.parentNode;
if(targetButton.classList == ('delete')){
deleteEntry(entry)
}else if(targetButton.classList == ('edit')){
editEntry(entry);
}
}
// //DELETE FUNCTION
const deleteEntry = (entry) =>{
console.log(entry.id)
entry_list.splice(entry.id, 1)
// entry.innerHTML = ''
console.log(entry.id)
addIncomes()
}
// EDIT FUNCTION
const editEntry = (entry) =>{
let Entry = entry_list[entry.id]
if(entry.type == "income"){
incomeAmount.value = Entry.amount;
incomeTitle.value = Entry.title;
}else if(entry.type == "expense"){
expenseAmount.value = Entry.amount;
expenseTitle.value = Entry.title;
}
deleteEntry(entry);
}
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&family=Raleway:wght@400;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Open Sans', sans-serif;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.budget-container{
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100%;
background-color: #4F98CA;
}
.balance-container{
width: 360px;
height: 470px;
background-color: #50D890;
border-radius: 30px;
margin-right: 100px;
}
.app-title{
color: white;
margin-top: 1rem;
margin-left: 1rem;
}
.month{
color: white;
margin-top: 1rem;
text-align: center;
}
.budget-header{
display: flex;
flex-direction:column;
justify-content: center;
}
.balance{
margin-top: 1rem;
margin-left: 1rem;
}
.title{
color: white;
font-size: 1.25rem;
opacity: .75;
}
.value{
font-size: 1.75rem;
color: white;
font-weight: bold;
margin-left: 1rem;
}
.account{
margin-top: 2.5rem;
margin: 2.5rem 1.5rem 2.5rem 1.5rem;
display: flex;
justify-content: space-between
}
.income-total{
color: white;
text-align: center;
font-size: 1.5rem;
}
.outcome-total{
color: #4F98CA;
text-align: center;
font-size: 1.5rem;
}
/* DASHBOARD */
.budget-dashboard{
display: block;
width: 360px;
height: 470px;
position: relative;
border-radius: 30px;
background-color: white;
}
.dash-title{
margin-top: 2rem;
margin-left: 1rem;
font-size: 1.5rem;
}
.toggle{
margin: 1rem;
display: flex;
cursor: pointer;
}
.toggle .tab2, .tab3{
margin-left: 1rem;
cursor: pointer;
}
.clicked{
font-weight: bold !important;
}
.hidden{
display: none !important;
}
/* EXPENSES TAB */
.expense-tab{
display: flex;
justify-content: center;
}
.expense-input-container{
position: absolute;
top: 400px;
border-top: solid 1px gray;
width: 100%;
}
.expense-amount-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.expense-title-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.add-expense{
color: none;
background-color: none;
border: none;
outline: none;
color: inherit;
}
/* INCOME TAB */
.income-tab{
display: flex;
justify-content: center;
}
.income-input-container{
position: absolute;
top: 400px;
border-top: solid 1px gray;
width: 100%;
}
.input{
display: flex;
justify-content: space-between;
align-items: center;
margin: 1rem;
}
.income-amount-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.income-title-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.add-income{
color: none;
background-color: none;
border: none;
outline: none;
}
.plus-img{
width: 40px;
}
/* li */
ul{
width: 360px;
height: 255px;
list-style: none;
margin-top:20px;
overflow-x: auto;
}
/* BUTTON ICONS */
.edit{
background-image: url('media/Icons/icons8-edit-48.png');
background-size: contain;
width: 25px;
height: 25px;
background-repeat: no-repeat;
margin-right: 10px;
}
.delete{
background-image: url('media/Icons/icons8-trash-can-48 (2).png');
background-size: contain;
width:25px;
height: 25px;
background-repeat: no-repeat;
}
.income{
width:250px;
height: auto;
padding-left: 20px;
margin-bottom: 10px;;
word-wrap: break-word;
color: black
}
.expense{
width:250px;
height: auto;
padding-left: 20px;
margin-bottom: 10px;;
word-wrap: break-word;
font-family: 'Gilroy Bold';
color: #4F98CA;
}
li{
display: flex;
justify-content: space-between;
width: 100% !important;
padding-right: 20px;
}
.icon-container{
display: flex;
}
@media (max-width:900px){
.budget-container{
display: inline-block;
position: relative
}
.balance-container{
position: absolute;
top: 10%;
left: 25%;
}
.budget-dashboard{
position: absolute;
left: 25%;
top: 40%;
}
}
<!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.0">
<link rel="stylesheet" href="style.css">
<title>Budgetrr</title>
</head>
<body>
<main class="budget-container">
<section class="balance-container">
<div class="app-title">
<p>Budgetrr</p>
</div>
<h1 class="month">OCTOBER</h1>
<section class="budget-header">
<div class="balance">
<div class="title">
Balance
</div>
<div class="value">
<small>$</small>0
</div>
</div>
<div class="account">
<div class="budget-income">
<div class="title">
Income
</div>
<div class="income-total">
<small>$</small>0
</div>
</div>
<div class="chart"></div>
<div class="budgetoutcome">
<div class="title">
Expenses
</div>
<div class="outcome-total">
<small>$</small>0
</div>
</div>
</div>
</section>
</section>
<section class="budget-dashboard">
<div class="dash-title">Dashboard</div>
<div class="toggle">
<div class="tab1 clicked">Expenses</div>
<div class="tab2">Income</div>
<!-- <div class="tab3 clicked">All</div> -->
</div>
<div class="income-tab hidden">
<ul class="list"></ul>
<div class="income-input-container">
<form class="input">
<input type="text" class="income-title-input" name="title" placeholder="Title">
<input type="number" class="income-amount-input" name="amount" placeholder="$0">
<button type = "button" class="add-income"><img class= "plus-img"src="media/Icons/icons8-add-new-48.png" alt=""></button>
</form>
</div>
</div>
<div class = "expense-tab">
<ul class="list"></ul>
<div class="expense-input-container">
<div class="input">
<input type="text" class="expense-title-input" name="title" placeholder="Title">
<input type="number" class="expense-amount-input" name="amount" placeholder="$0">
<button type="button" class="add-expense"><img class= "plus-img" src="media/Icons/icons8-add-new-48.png" alt=""></button>
</div>
</div>
</div>
</section>
</main>
<script src="JavaScript/budget.js"></script>
</body>
</html>
I've tried to use .splice() but I can't seem to get it to work.