I am working on "to do list" using Vanilla JavaScript and stuck with edit button.
This is what I have done so far.
// console.log("Hello from inside");
const input = document.getElementById("inputText");
const display = document.getElementById("display");
const displayDone = document.getElementById("display-done");
const button = document.getElementById("addButton");
const deleteAll = document.getElementById("delete-icon");
// const ul = document.getElementById("display");
// Create and Remove list item
function createItem() {
let listItem = document.createElement("li");
listItem.className = "create";
listItem.appendChild(document.createTextNode(input.value));
display.appendChild(listItem);
input.value = "";
let editButton = document.createElement("button");
editButton.innerText = "edit";
editButton.className = "edit";
editButton.addEventListener("click", (e) => {
//console.log(e.currentTarget.parentNode);
// 1. When edit button is clicked, change list item to be an input text. <input type="text" value="my to do task"/>
// 2. Change edit button to be something like "complete" button
editButton.innerText = "complete";
// 3. When complete button is clicked, change the input item to be a list item again with the updated text.
editButton.addEventListener("click", (e) => {
editButton.innerText = "edit";
});
});
let removeTask = document.createElement("input");
removeTask.setAttribute("type", "button");
removeTask.setAttribute("value", "X");
removeTask.setAttribute("id", "removeButton");
removeTask.addEventListener("click", (e) => {
listItem.parentNode.removeChild(listItem);
});
listItem.appendChild(editButton);
listItem.appendChild(removeTask);
listItem.addEventListener("dblclick", (e) => {
displayDone.appendChild(listItem);
listItem.style.backgroundColor = "#54e346";
listItem.style.textDecoration = "line-through";
editButton.style.display = "none";
});
}
//Make sure user fill the input
function addAfterClick() {
if (input.value.length > 0) {
createItem();
} else {
alert("Write something mate!");
}
}
//List item can be added with "Enter" as well
function addWithEnter(event) {
if (event.keyCode === 13) {
addAfterClick();
}
}
// Remove all with user approve
function removeAll(event) {
let answer = prompt(`Type "Delete All" If you are that sure!`);
if (answer === "Delete All") {
display.style.display = "none";
location.reload();
} else {
alert("Try One More Time");
}
}
//Event Listeners
button.addEventListener("click", addAfterClick);
input.addEventListener("keyup", addWithEnter);
deleteAll.addEventListener("click", removeAll);
<div class="main-container">
<h2 class="title">to do list <i class="fas fa-pencil-alt"></i></h2>
<div class="content">
<input
id="inputText"
type="text"
placeholder="Add to your list..."
maxlength="20"
/>
<i id="addButton" class="fas fa-plus"></i>
<div class="remove-container">
<i id="delete-icon" class="far fa-trash-alt"></i>
<p id="remove-text">Delete All</p>
</div>
<ul id="display"></ul>
</div>
<div class="completed">
<h2 class="title-done">
completed tasks <i class="far fa-check-circle"></i>
</h2>
<ul id="display-done"></ul>
</div>
</div>
What I want to do it;
When edit button is clicked, change list item to be an input text.
Change edit button to be something like "complete" button
When complete button is clicked, change the input item to be a list item again with the updated text.
I have tried ChildNode.replaceWith() but did not work. Am I on the right path? and also what direction(s) I should follow. Thanks in advance!
My approach is to add an input field everytime you create an item:
at initial insertion hide the input field
on click on the edit button show the input and change the textNode
after you editing
console.log("Hello from inside");
const input = document.getElementById("inputText");
const display = document.getElementById("display");
const displayDone = document.getElementById("display-done");
const button = document.getElementById("addButton");
const deleteAll = document.getElementById("delete-icon");
// const ul = document.getElementById("display");
// create edit input and hide the input at first
const editInput=document.createElement("input");
editInput.setAttribute("hidden",true);
// eventhandler for editInput
function editItem(e,item){
// remove the current text node
e.target.parentNode.removeChild(e.target.parentNode.childNodes[0])
// insert at the beginning of the childNodes
e.target.parentNode.prepend( e.target.value)
e.target.setAttribute("hidden",true)
}
// Create and Remove list item
function createItem() {
let listItem = document.createElement("li");
listItem.className = "create";
listItem.appendChild(document.createTextNode(input.value));
display.appendChild(listItem);
input.value = "";
let editButton = document.createElement("button");
editButton.innerText = "edit";
editButton.className = "edit";
editInput.value=""
editButton.addEventListener("click", (e) => {
// 1. When edit button is clicked, change list item to be an input text. <input type="text" value="my to do task"/>
// 2. Change edit button to be something like "complete" button
// appended edit input
listItem.append(editInput)
if(e.target.innerText === "edit"){
editInput.removeAttribute("hidden",false)
e.target.innerText = "complete";
}else{
e.target.innerText = "edit";
}
// add the event handler for the Editinput
editInput.addEventListener("change",(e)=>editItem(e,listItem));
editInput.value=""
// 3. When complete button is clicked, change the input item to be a list item again with the updated text.
});
let removeTask = document.createElement("input");
removeTask.setAttribute("type", "button");
removeTask.setAttribute("value", "X");
removeTask.setAttribute("id", "removeButton");
removeTask.addEventListener("click", (e) => {
listItem.parentNode.removeChild(listItem);
});
listItem.appendChild(editButton);
listItem.appendChild(removeTask);
listItem.addEventListener("dblclick", (e) => {
displayDone.appendChild(listItem);
listItem.style.backgroundColor = "#54e346";
listItem.style.textDecoration = "line-through";
editButton.style.display = "none";
});
}
//Make sure user fill the input
function addAfterClick() {
if (input.value.length > 0) {
createItem();
} else {
alert("Write something mate!");
}
}
//List item can be added with "Enter" as well
function addWithEnter(event) {
if (event.keyCode === 13) {
addAfterClick();
}
}
// Remove all with user approve
function removeAll(event) {
let answer = prompt(`Type "Delete All" If you are that sure!`);
if (answer === "Delete All") {
display.style.display = "none";
location.reload();
} else {
alert("Try One More Time");
}
}
//Event Listeners
button.addEventListener("click", addAfterClick);
input.addEventListener("keyup", addWithEnter);
deleteAll.addEventListener("click", removeAll);
<div class="main-container">
<h2 class="title">to do list <i class="fas fa-pencil-alt"></i></h2>
<div class="content">
<input
id="inputText"
type="text"
placeholder="Add to your list..."
maxlength="20"
/>
<i id="addButton" class="fas fa-plus"></i>
<div class="remove-container">
<i id="delete-icon" class="far fa-trash-alt"></i>
<p id="remove-text">Delete All</p>
</div>
<ul id="display"></ul>
</div>
<div class="completed">
<h2 class="title-done">
completed tasks <i class="far fa-check-circle"></i>
</h2>
<ul id="display-done"></ul>
</div>
</div>
just a suggestion. you can use an input element for each item.
const input = document.getElementById("inputText");
const display = document.getElementById("display");
const displayDone = document.getElementById("display-done");
const button = document.getElementById("addButton");
const deleteAll = document.getElementById("delete-icon");
const createEditBtn = () => {
const editButton = document.createElement("button");
editButton.innerText = "edit";
editButton.className = "edit";
editButton.addEventListener("click", (e) => {
const btn = e.target;
const input = btn.parentElement.querySelector("input");
input.focus();
const previousVal = input.value;
input.addEventListener("keyup", (evt) => {
if (evt.keyCode === 13) {
if (input.value.trim() === "") {
input.value = previousVal;
}
input.disabled = true;
btn.disabled = false;
}
});
input.addEventListener("blur", () => {
input.disabled = true;
btn.disabled = false;
});
input.disabled = false;
btn.disabled = true;
});
return editButton;
}
const createRemoveBtn = () => {
const removeBtn = document.createElement("input");
removeBtn.setAttribute("type", "button");
removeBtn.setAttribute("value", "X");
removeBtn.addEventListener("click", (e) => {
e.target.parentElement.remove();
});
return removeBtn;
}
const createItem = () => {
const listItem = document.createElement("li");
listItem.innerHTML = `<input value="${input.value}" disabled=true>`;
display.appendChild(listItem);
input.value = "";
const editBtn = createEditBtn();
listItem.appendChild(editBtn);
listItem.appendChild(createRemoveBtn());
listItem.addEventListener("dblclick", (e) => {
displayDone.appendChild(listItem);
listItem.style.backgroundColor = "#54e346";
listItem.style.textDecoration = "line-through";
editBtn.style.display = "none";
});
}
const addAfterClick = () => {
if (input.value.length > 0) {
createItem();
} else {
alert("Write something mate!");
}
}
//List item can be added with "Enter" as well
const addWithEnter = (event) => {
if (event.keyCode === 13) {
addAfterClick();
}
}
// Remove all with user approve
const removeAll = (event) => {
const answer = prompt(`Type "Delete All" If you are that sure!`);
if (answer === "Delete All") {
display.innerHTML = "";
displayDone.innerHTML = "";
} else {
alert("Try One More Time");
}
}
//Event Listeners
button.addEventListener("click", addAfterClick);
input.addEventListener("keyup", addWithEnter);
deleteAll.addEventListener("click", removeAll);
<div class="main-container">
<h2 class="title">to do list <i class="fas fa-pencil-alt"></i></h2>
<div class="content">
<input id="inputText" type="text" placeholder="Add to your list..." maxlength="20" />
<i id="addButton" class="fas fa-plus">add Icon</i>
<div class="remove-container">
<i id="delete-icon" class="far fa-trash-alt">delete icon</i>
<p id="remove-text">Delete All</p>
</div>
<ul id="display"></ul>
</div>
<div class="completed">
<h2 class="title-done">
completed tasks <i class="far fa-check-circle"></i>
</h2>
<ul id="display-done"></ul>
</div>
</div>
Related
I am a new learner and I am facing a problem. I want to create a simple messaging app and I want that if there is no text inside the input field then the button should be disabled. Help me out.
Here is the code:
let sendMessage = document.getElementById("sendMessage");
sendMessage.addEventListener("click", () => {
let val = document.getElementById("val");
let p = document.createElement("p");
let pTxt = document.createTextNode(val.value);
p.appendChild(pTxt);
val.value = "";
let messages = document.getElementById("messages");
messages.appendChild(p);
if (val.value === "") {
sendMessage.disabled = true;
} else {
sendMessage.disabled = false;
}
});
<div id="messages"></div>
<input type="text" id="val" />
<button id="sendMessage">Send</button>
You should use input event to set disabled to false or true. Set disabled to true by default and after button was clicked.
let sendMessage = document.getElementById("sendMessage");
let input = document.getElementById("val");
sendMessage.addEventListener("click", () => {
let val = document.getElementById("val");
let p = document.createElement("p");
let pTxt = document.createTextNode(val.value);
p.appendChild(pTxt);
val.value = "";
let messages = document.getElementById("messages");
messages.appendChild(p);
sendMessage.disabled = true;
});
input.addEventListener("input", () => {
if(input.value.length > 0){
sendMessage.disabled = false;
} else {
sendMessage.disabled = true;
}
});
<body>
<div id="messages"></div>
<input type="text" id="val"/>
<button id="sendMessage" disabled>Send</button>
<script src="app.js" type="text/javascript"></script>
</body>
Simply create a disabled class for the button if you use custom button.
Then listen to the input change and toggle the class on button if the input have value.
With your code :
const button = document.getElementById('sendMessage');
const input = document.getElementById('message-input');
const messagesBox = document.getElementById('messages');
input.addEventListener('input', () => sendMessage.disabled = input.value === '');
button.addEventListener('click', () => {
let p = document.createElement('p');
let pTxt = document.createTextNode(input.value);
p.appendChild(pTxt);
messagesBox.appendChild(p);
});
<body>
<div id="messages"></div>
<input type="text" id="message-input" />
<button id="sendMessage" disabled >Send</button>
<script src="app.js" type="text/javascript"></script>
</body>
Set a keyup input handler for the input field and a click handler for the button. In the snippet event delegation is used.
document.addEventListener(`input`, handle);
document.addEventListener(`click`, handle);
function handle(evt) {
const isInput = evt.target.closest(`#val`);
const isBttn = evt.target.closest(`#sendMessage`);
if (isInput) {
document.querySelector(`#sendMessage`).disabled = !isInput.value.trim();
}
if (isBttn) {
isBttn.disabled = isBttn;
const inputField = document.querySelector(`#val`);
document.querySelector(`#messages`).insertAdjacentHTML(`beforeend`,
`<li>${inputField.value.trim()}</li>`);
inputField.value = ``;
inputField.focus();
}
}
<ul id="messages"></ul>
<input type="text" id="val" />
<button id="sendMessage" disabled>Send</button>
I wanted to create my own To-do list app and I have a problem when I edit a task the area with three buttons (accept, edit and cancel btns) sometimes goes missing.
I'm trying to figure out what's happening with it in the dev tools and it looks like when there are e.g. two tasks (two li elements) the div area with buttons move from one to another and the second li has two divs and the first li (edited one) it left with no buttons at all.
Here's my code, please excuse any weird things you may find there (I'm not really experienced).
const inputField = document.querySelector('.todo__input')
const addBtn = document.querySelector('.todo__btn')
const ulList = document.querySelector('.todo__list')
const infoParagraph = document.querySelector('.todo__info-paragraph')
const popupDiv = document.querySelector('.pop-up')
const popupAcceptBtn = document.querySelector('.edit-accept')
const popupCancelBtn = document.querySelector('.edit-cancel')
const popupInput = document.querySelector('.edit__input')
const popupInfo = document.querySelector('.edit__info')
let liItem
let acceptButton
let editButton
let cancelButton
let editedTodoTask
let editBtnToBeDisabled
const createLiSpace = () => {
const div = document.createElement('div')
div.classList.add('todo__list-buttons')
liItem.append(div)
acceptButton = document.createElement('button')
acceptButton.classList.add('todo__list-btn')
acceptButton.classList.add('todo__list-btn--accept')
acceptButton.innerHTML = '<i class="fa-solid fa-check"></i>'
editButton = document.createElement('button')
editButton.classList.add('todo__list-btn')
editButton.classList.add('todo__list-btn--edit')
editButton.innerHTML = '<i class="fa-solid fa-pencil"></i>'
cancelButton = document.createElement('button')
cancelButton.classList.add('todo__list-btn')
cancelButton.classList.add('todo__list-btn--cancel')
cancelButton.innerHTML = '<i class="fa-solid fa-xmark"></i>'
div.append(acceptButton, editButton, cancelButton)
acceptButton.addEventListener('click', completeTask)
editButton.addEventListener('click', showPopup)
cancelButton.addEventListener('click', deleteTask)
}
const addTask = () => {
if (inputField.value !== '') {
liItem = document.createElement('li')
liItem.classList.add('todo__list-item')
liItem.textContent = inputField.value
createLiSpace()
ulList.appendChild(liItem)
inputField.value = ''
infoParagraph.textContent = ''
} else if (inputField.value == '') {
infoParagraph.style.color = 'rgb(206, 99, 28)'
infoParagraph.textContent = 'Please type in your task first!'
}
}
const showPopup = e => {
editedTodoTask = e.target.closest('li')
popupDiv.style.visibility = 'visible'
popupInfo.textContent = ''
popupInput.value = editedTodoTask.firstChild.textContent
}
const changeTodoTask = () => {
if (popupInput.value !== '') {
editedTodoTask.textContent = popupInput.value
createLiSpace()
closePopup()
popupInput.value = ''
} else {
popupInfo.textContent = 'Please type in some text here...'
}
}
const enterAddTask = (e) => {
if (e.key == "Enter") {
addTask()
}
}
const completeTask = e => {
editedTodoTask = e.target.closest('li')
editedTodoTask.classList.toggle('crossline')
}
const closePopup = () => {
popupDiv.style.visibility = 'hidden'
}
const deleteTask = e => {
ulList.removeChild(e.target.closest('li'))
}
popupAcceptBtn.addEventListener('click', changeTodoTask)
popupCancelBtn.addEventListener('click', closePopup)
addBtn.addEventListener('click', addTask)
inputField.addEventListener('keyup', enterAddTask)
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<div class="container">
<div class="todo-top-section">
<h1 class="todo__header">My to-do list</h1>
<input type="text" placeholder="Type your task here..." class="todo__input">
<button class="todo__btn"><img class="todo__blob" src="/src/img/blobanimation.svg" alt="">add</button>
</div>
<div class="todo-bottom-section">
<h2 class="todo__heading">Task list:</h2>
<p class="todo__info-paragraph">No tasks here yet</p>
<ul class="todo__list">
</ul>
</div>
<div class="pop-up">
<h3 class="edit__header">Want to change anything in here?</h3>
<p class="edit__info"></p>
<div class="edit-container">
<input type="text" class="edit__input" placeholder="Type in your change...">
<div class="todo__list-buttons">
<button class="todo__list-btn todo__list-btn--accept edit-accept">Accept <i class="fa-solid fa-check"></i></button>
<button class="todo__list-btn todo__list-btn--cancel edit-cancel">Cancel <i class="fa-solid fa-xmark"></i></button>
</div>
</div>
</div>
Could you please check and specify what is causing that trouble?
You can find my code here too: https://codepen.io/re_aleksandra/pen/PoebEPv
Thank you!
Other stack answers have failed to fix my problem because I think this occurs for different reasons. My JS code:
const addButton = document.querySelector('.addButton')
var input = document.querySelector('.input')
const draggable_list = document.getElementById('draggable-list'); //draggable_list is a ul
let itemBox;
let items;
const array = [];
const listItems = [];
let dragStartIndex;
class item {
constructor(itemName) {
this.createDiv(itemName);
}
createDiv(itemName) {
let removeButton = document.createElement('button');
removeButton.innerHTML = 'REMOVE';
removeButton.classList.add('removeButton');
draggable_list.appendChild(items);
items.appendChild(removeButton);
removeButton.addEventListener('click', () => this.remove(items);
}
async remove(item, value) {
draggable_list.removeChild(item)
}
}
async function check() {
if (input.value != '') {
array.push(input.value)
listItems.push(input.value)
array.forEach((numbers,index) => {
items = document.createElement('li')
items.setAttribute('data-index', index)
items.innerHTML = `
<div class="draggable" draggable="true">
<p class="phone-number">${numbers}</p>
<i class="fas fa-grip-lines"></i>
</div>`;
} )
new item(input.value)
input.value = ''
}
addButton.addEventListener('click', check)
When remove() is called for the first time, it successfully removes the last li element. But when it is called again, I get the following error:
Uncaught (in promise) DOMException: Node.removeChild: The node to be removed is not a child of this node
Does this work for you...
const addButton = document.querySelector('.addButton');
const input = document.querySelector('.input');
const draggable_list = document.getElementById('draggable-list');
//draggable_list is a ul
let itemBox;
let items;
const array = [];
const listItems = [];
let dragStartIndex;
class Item {
constructor(itemName) {
this.createDiv(itemName);
}
createDiv(itemName) {
let input = document.createElement('input');
input.value = itemName;
let removeButton = document.createElement('button');
removeButton.innerHTML = 'REMOVE'
removeButton.classList.add('removeButton');
draggable_list.appendChild(items);
items.appendChild(removeButton);
removeButton.addEventListener('click', (event) => {
if (event && event.target.parentElement) {
// this.remove(items));
this.remove(event.target.parentElement);
}
});
}
remove(item, value) {
draggable_list.removeChild(item);
}
}
function check() {
if (input.value != '') {
array.push(input.value);
listItems.push(input.value);
array.forEach((numbers, index) => {
items = document.createElement('li');
items.setAttribute('data-index', index)
items.innerHTML = `
<div class="draggable" draggable="true">
<p class="phone-number">${numbers}</p>
<i class="fas fa-grip-lines"></i>
</div>`;
});
new Item(input.value);
input.value = '';
}
}
addButton.addEventListener('click', check)
<button class="addButton">+</button>
<input type="text" class="input" />
<ul id="draggable-list">
</ul>
Instead of copying and pasting some convoluted code you don't understand you should try and write it yourself. Try and focus on what you require and nothing else.
Here is one way of doing it:
const [inp,btn,ul]=["input","button","ul"].map(e=>document.querySelector(e));
btn.onclick=function(){
ul.innerHTML+=`<li><p>${inp.value}</p><button>delete</button></li>`;
inp.value="";
}
ul.onclick=function(ev){
if (ev.target.tagName==="BUTTON")
ul.removeChild(ev.target.closest("li"));
}
<input type="text">
<button>add</button>
<ul></ul>
So i have following objectives from the checkbox click event
1] Create A Button having id = 'id-of-checkbox'+'some-character-here' in specified div
2] Clicking On That Particular Button Will Remove The Button As Well As Checkbox tick related to it
3] If User wants to remove button in specified div through unchecking the checkbox it should be done
4] And If User again checks the checkbox button should be created in specified div
Now i have achieved first 3 objectives and im having issue with 4th one , i.e
if i click on checkbox again after unticking it button is not getting created and console doesnt return any error associated with it.. please help
Here Is My HTML Code
<div id="filterDropArea container">
<input type="checkbox" name="priceFilter" id="priceFilter" class="btn" onclick="updateValue(this.id,this.name)">
Price Filter
</div>
<div id="DropArea">
</div>
Here is My Javascript Code
var objTo = document.getElementById('DropArea');
var checked = ""
function updateValue(id,name)
{
if(document.getElementById(id).checked)
{
checked='yes'
}
else if(!document.getElementById(id).checked)
{
checked='no'
}
if(checked=='yes')
{
addButton(id,name);
}
else if(checked=='no')
{
removeButton(id,name);
}
}
function addButton(id,name)
{
var nameOfButton = name+'X';
var idofButton = id+'11';
var btn = document.createElement("BUTTON");
btn.innerHTML=nameOfButton;
btn.setAttribute("class","btnCancel");
btn.setAttribute("id",idofButton);
btn.setAttribute("onclick","someMsg(this.id)")
objTo.appendChild(btn);
}
function removeButton(id,name)
{
var idofButton = id+'11'
if(document.getElementById('DropArea').contains(document.getElementById(idofButton)))
{
document.getElementById('DropArea').remove(document.getElementById(idofButton));
console.log('Button Removed');
}
}
function someMsg(id)
{
var name = id.substring(0,id.length-2);
document.getElementById(id).remove();
document.getElementById(name).checked=false;
console.log('Deleted');
}
Another approach to achieving the same result:
const dropArea = document.querySelector("#dropArea");
const checkbox = document.querySelector("#priceFilter");
checkbox.addEventListener("change", function(e) {
if (this.checked) {
const btn = createSpecificButton();
dropArea.appendChild(btn);
} else {
const btn = dropArea.querySelector("button");
dropArea.removeChild(btn);
}
});
const createSpecificButton = () => {
const btn = document.createElement("button");
btn.innerText = "Click Here";
btn.addEventListener("click", function(e) {
checkbox.checked = false;
this.remove();
});
return btn;
};
<div id="filterDropArea container">
<input type="checkbox" name="priceFilter" id="priceFilter" /> Price Filter
</div>
<div id="dropArea"></div>
Element.remove() don't have any parameters, so when you call by your way, it will remove DropArea element (includes children, like idofButton).
Solution: Change the below line
document.getElementById('DropArea').remove(document.getElementById(idofButton));
To
document.getElementById(idofButton).remove();
var objTo = document.getElementById('DropArea');
var checked = ""
function updateValue(id, name) {
if (document.getElementById(id).checked) {
checked = 'yes'
} else if (!document.getElementById(id).checked) {
checked = 'no'
}
if (checked == 'yes') {
addButton(id, name);
} else if (checked == 'no') {
removeButton(id, name);
}
}
function addButton(id, name) {
var nameOfButton = name + 'X';
var idofButton = id + '11';
var btn = document.createElement("BUTTON");
btn.innerHTML = nameOfButton;
btn.setAttribute("class", "btnCancel");
btn.setAttribute("id", idofButton);
btn.setAttribute("onclick", "someMsg(this.id)")
objTo.appendChild(btn);
}
function removeButton(id, name) {
var idofButton = id + '11'
if (document.getElementById('DropArea').contains(document.getElementById(idofButton))) {
document.getElementById(idofButton).remove();
console.log('Button Removed');
}
}
function someMsg(id) {
var name = id.substring(0, id.length - 2);
document.getElementById(id).remove();
document.getElementById(name).checked = false;
console.log('Deleted');
}
<div id="filterDropArea container">
<input type="checkbox" name="priceFilter" id="priceFilter" class="btn" onclick="updateValue(this.id,this.name)"> Price Filter
</div>
<div id="DropArea">
</div>
I'm creating a CRUD page where the user can add, delete and edit text, but I have an issue in updating the text after I select it for edit.
In editText function when I click the edit button the text that was added will pop up inside the input field. When I click on the update button (triggering the updateText function), I can see the text in console log but the corresponding html is not updated.
HTML
<div class="main">
<form>
<input type="text" placeholder="search">
</form>
<ul></ul>
<div>
<input class="add-text" type="text" placeholder="Add Text">
<button id="add">Add</button>
<button id="update">update</button>
</div>
</div>
Javascript
const inputsearch = document.querySelector('form input');
const addInputBtn = document.querySelector('#add');
const update = document.querySelector('#update');
addInputBtn.addEventListener('click', addtext);
function addtext(){
let li = document.createElement('li');
let inputadd = document.querySelector('.add-text');
let addedtext = inputadd.value;
let h1Tag = '<h1 id="text">'+addedtext+'</h1>';
let tags = h1Tag + '<button id="delete">Delete</button><button id="edit">Edit</button>';
if(addedtext == ''){
alert('please add some text');
return;
}else{
li.innerHTML = tags;
document.querySelector('ul').appendChild(li);
}
li.querySelectorAll('#delete')[0].addEventListener('click', deleteText);
li.querySelectorAll('#edit')[0].addEventListener('click', editText);
getlist(li, h1Tag);
inputadd.value = '';
}
function deleteText(e) {
e.target.parentNode.remove();
document.querySelector('.add-text').value = '';
}
function editText(e) {
let currentText = e.target.parentNode.firstChild.textContent;
let currentValue = document.querySelector('.add-text');
currentValue.value = currentText;
getupdate(currentText, currentValue);
}
function getupdate(currentText, currentValue) {
update.addEventListener('click', updateText);
function updateText() {
currentText = currentValue.value
console.log(currentText = currentValue.value);
}
}
function getlist(li, h1Tag) {
inputsearch.addEventListener('keyup', serchText);
function serchText(e) {
let typetext = e.target.value.toLowerCase();
if(h1Tag.toLowerCase().indexOf(typetext) != -1){
li.style.display = 'block';
}else{
li.style.display = 'none';
}
}
}
To solve the issue without changing your overall approach, your edit button click needs to get the corresponding element (not just its textContent) and pass it to your getupdate() function to be updated when your update button is clicked. Relatively minor changes to your current functions:
function editText(e) {
const currentText = e.target.parentNode.firstChild;
const currentValue = document.querySelector('.add-text');
currentValue.value = currentText.textContent;
getupdate(currentText, currentValue);
}
function getupdate(currentText, currentValue) {
update.addEventListener('click', updateText);
function updateText() {
currentText.textContent = currentValue.value;
}
}
There are some other issues with your code, particularly the creation of multiple elements with the same id (which is malformed and will likely become problematic as you add additional features). Following is a snippet that addresses that issue as well as simplifying some of your functions and fixing the search.
const search = document.querySelector('form input');
const input = document.querySelector('.add-text');
const container = document.querySelector('ul');
let items = null;
let currentItem = null;
const searchItems = (event) => {
if (items) {
const s = event.currentTarget.value.toLowerCase();
for (const item of items) {
if (item.firstChild.textContent.toLowerCase().indexOf(s) !== -1) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
}
}
};
const deleteItem = (event) => {
currentItem = null;
event.currentTarget.parentNode.remove();
};
const editItem = (event) => {
currentItem = event.currentTarget.parentNode.firstChild;
input.value = currentItem.textContent;
};
const updateItem = () => {
if (currentItem) {
currentItem.textContent = input.value;
}
};
const addItem = () => {
let val = input.value
if (val) {
const li = document.createElement('li');
let inner = '<h1 class="text">' + val + '</h1>';
inner += '<button class="delete">Delete</button>';
inner += '<button class="edit">Edit</button>';
li.innerHTML = inner;
container.appendChild(li);
val = '';
currentItem = li.firstChild;
items = document.querySelectorAll('li');
for (let del of document.querySelectorAll('.delete')) {
del.addEventListener('click', deleteItem);
}
for (let edit of document.querySelectorAll('.edit')) {
edit.addEventListener('click', editItem);
}
} else {
alert('please add some text');
return;
}
};
search.addEventListener('keyup', searchItems);
document.querySelector('#add').addEventListener('click', addItem);
document.querySelector('#update').addEventListener('click', updateItem);
<div class="main">
<form>
<input type="text" placeholder="Search">
</form>
<ul></ul>
<div>
<input class="add-text" type="text" placeholder="Add Text">
<button id="add">Add</button>
<button id="update">Update</button>
</div>
</div>