JavaScript removeChild input from the dom - javascript

I'm trying to delete the form input posted onto the DOM, but the removeChild code isn't functioning, When inspecting the console I will be given an error which is: materialize.min.js:6 Uncaught TypeError: Cannot read property 'M_Modal' of null at HTMLBodyElement.value (materialize.min.js:6)
// ----------------Models Materialize Framework----------------
document.addEventListener('DOMContentLoaded', () => {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
});
//Delete Exercises
const delExerciseBtn = document.querySelector('.del-exercise-btn');
delExerciseBtn.addEventListener('click', (e) => {
if(e.target.className == 'delete'){
const h6 = e.target.parentElement;
h6.removeChild(e.target);
}
});
// Add User's To the Dom.
const addExerciseDom = document.querySelector('.exercise-dom');
const exerciseForm = document.querySelector('.exercises-form');
exerciseForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get Input Value
const value = exerciseForm.querySelector('input[type="text"]').value;
// Create Elements
const h6 = document.createElement('h6');
// Add Content
h6.textContent = value;
// Append To Dom
addExerciseDom.appendChild(h6);
});

For Multiple Values of h6
Best to add id with each new h6
Check on weight and exercise
// Materialize Initialization Of Autocomplete, Exercise.
document.addEventListener('DOMContentLoaded', () => {
var elems = document.querySelectorAll('.autocomplete');
var instances = M.Autocomplete.init(elems,{
data: {
"Lat Pull Down": null,
"Lat Down": null,
},
limit:2,
minLength:1,
});
});
// Materialize Initialization Of Box Select, Sets and Reps.
document.addEventListener('DOMContentLoaded', () => {
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
});
// Materialize Initialization Of Weights CharacterCount
document.addEventListener('DOMContentLoaded', () => {
var textNeedCount = document.querySelectorAll('.weightcountercount');
M.CharacterCounter.init(textNeedCount);
});
//need to put restrition on the number typed into the box without it submitting
// ----------------Models Materialize Framework----------------
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
});
// ------------ Add Form's Inputs Onto The HomePage----------------
//-------------Exercises------------
// Delete Exercises From The Dom
const delExerciseBtn = document.querySelector('.del-exercise-btn');
delExerciseBtn.addEventListener('click', (e) => {
// Remove Form Input
const h6_e = document.getElementById('h6_exercise');
h6_e.remove();
// Remove Disable Btn
disabledExersiceBtn.removeAttribute('disabled');
});
// Add User's Exercises To The Dom.
const addExerciseDom = document.querySelector('.exercise-dom');
const exerciseForm = document.querySelector('.exercises-form');
const disabledExersiceBtn = document.querySelector('.disabled-exersicebtn');
exerciseForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get Input Value
const value = exerciseForm.querySelector('input[type="text"]').value;
// Create Elements
// const h6 = document.createElement('h6');
//for exercise
const h6_exercise = document.createElement('h6');
// Add Content
h6_exercise.textContent = value;
//adding id
h6_exercise.setAttribute("id", "h6_exercise");
// Append To Dom
addExerciseDom.appendChild(h6_exercise);
//Disable Btn
disabledExersiceBtn.setAttribute('disabled', 'disabled');
});
//---------------------Weight----------------------
// Delete Exercises From The Dom
const delWeightBtn = document.querySelector('.del-weight-btn');
delWeightBtn.addEventListener('click', (e) => {
// Remove Form Input
let h6_r = document.getElementById('h6_weight');
h6_r.remove();
});
// Add User's Weight To The Dom.
const addWeightDom = document.querySelector('.weight-dom');
const weightForm = document.querySelector('.weight-form');
weightForm.addEventListener('submit', (e) => {
e.preventDefault();
if(document.getElementById('h6_weight'))
{
let h6_r = document.getElementById('h6_weight');
h6_r.remove();
}
// Get Input Value
const value = weightForm.querySelector('input[type="number"]').value;
const value1 = weightForm.querySelector('input[type="text"]').value;
//console.log(value, value1);
// Create Elements
const h6_weight = document.createElement('h6');
h6_weight.setAttribute('id','h6_weight')
//h6.classList.add("center");// not working
// Add Content
h6_weight.textContent = value + " " + value1;
// Append To Dom
addWeightDom.appendChild(h6_weight);
});
// ------------------Add Exercises Colum----------------------
//const addMoreBtn = document.getElementById("addmorebtn");
////const addColums = document.getElementById("addcolumns");
//addMoreBtn.addEventListener('click', (e) => {
// e.preventDefault();
// const text =
// `<div class="col s4 height"></div>
// <div class="col s2 height "></div>
// <div class="col s2 height"></div>
// <div class="col s2 height"></div>
// <div class="col s2 height"></div>`
//const position = "beforeend";
//addColums.insertAdjacentHTML(position, text);
//});

You can do it like this
// ----------------Models Materialize Framework----------------
document.addEventListener('DOMContentLoaded', () => {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
});
//Delete Exercises
const delExerciseBtn = document.querySelector('.del-exercise-btn');
delExerciseBtn.addEventListener('click', (e) => {
const h6 = document.getElementsByTagName('h6')[0];
h6.remove();
});
// Add User's To the Dom.
const addExerciseDom = document.querySelector('.exercise-dom');
const exerciseForm = document.querySelector('.exercises-form');
const disabledExersiceBtn = document.querySelector('.disabled-exersicebtn');
exerciseForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get Input Value
const value = exerciseForm.querySelector('input[type="text"]').value;
// Create Elements
const h6 = document.createElement('h6');
// Add Content
h6.textContent = value;
// Append To Dom
addExerciseDom.appendChild(h6);
//Disable Btn
disabledExersiceBtn.setAttribute('disabled', 'disabled');
});

Related

Removing input from the DOM and local storage with vanilla JavaScript

I'm creating a ToDo app in vanilla JavaScript.
My goal is to be able to remove the input data from local storage when the corresponding "X" button has been clicked.
So far, when you click on an X button, the corresponding input field and checkbox are removed from the DOM with this function I created -
function removeToDoInput(button, input1, input2, input3) {
if (allToDoInputs.length > 2) {
button.addEventListener("click", () => {
toDoInputContainer.removeChild(input1);
toDoInputContainer.removeChild(input2);
toDoInputContainer.removeChild(input3);
for (let toDoInput = 0; toDoInput < allToDoInputs.length; toDoInput++) {
for (let i = 0; i < localStorage.length; i++) {
localStorage.removeItem("ToDo " + toDoInput);
console.log("test");
}
}
})
}
}
This works fine. But like I mentioned I also need to remove the corresponding input data from local storage.
Here is the 'add-to-do' button functionality. You'll notice the removeToDoInput is called which I don't think is good -
function createToDoInput() {
const newToDoInputCheckbox = document.createElement("INPUT");
newToDoInputCheckbox.setAttribute("type", "checkbox");
const newToDoInput = document.createElement("INPUT");
const newXBtn = document.createElement("SPAN");
toDoInputContainer.appendChild(newToDoInputCheckbox);
toDoInputContainer.appendChild(newToDoInput);
toDoInputContainer.appendChild(newXBtn);
newToDoInputCheckbox.classList.add("checkbox");
newToDoInput.classList.add("to-do-input");
newXBtn.classList.add("X");
newXBtn.innerHTML = "X";
newXBtn.addEventListener("click", removeToDoInput(newXBtn, newToDoInputCheckbox, newToDoInput, newXBtn));
}
And here is the save button functionality -
function saveToDoInputs() {
localStorage.setItem("Title", toDoListTitle.value.trim());
for (let toDoInput = 0; toDoInput < allToDoInputs.length; toDoInput++) {
if (createToDoInput) {
localStorage.setItem("ToDo " + toDoInput, allToDoInputs[toDoInput].value.trim());
}
}
}
Both of these last functions I mentioned are attached to buttons through click event listeners.
How can I delete the input from local storage as well as the DOM?
This is incorrect and will be called immediately you assign the event handler
newXBtn.addEventListener("click", removeToDoInput(newXBtn, newToDoInputCheckbox, newToDoInput, newXBtn));
you need
newXBtn.addEventListener("click", function() { removeToDoInput(newXBtn, newToDoInputCheckbox, newToDoInput, newXBtn)});
or similar
I have redesigned your code and now it
wraps the elements in their own container
delegates click and change to the list container
use relative addressing (closest)
gives the todo a unique ID and stores it in an object
retrieves the object from local storage when loading
adds the object to localStorage when changed
I also added a select all and delete selected
NOTE I have commented the localStorage interaction out because stacksnippets do not allow access to localStorage. Just uncomment them on your page
let todos = {};
// const saveTodos = localStorage.getItem("ToDo");
// if (saveTodos) todos = JSON.parse(saveTodos);
const toDoInputContainer = document.getElementById("toDoInputContainer");
const toggleSelDel = () => {
document.getElementById("seldel").classList.toggle("hide",Object.keys(todos).length===0); // show if there are actual entries - we can toggle on existense of checkboxes instead
}
const saveAndToggle = (id,why) => {
// localStorage.setItem("ToDo",JSON.stringify(todos));
console.log(id, why);
toggleSelDel()
};
const saveTodo = (id, text) => {
todos[id] = text;
saveAndToggle(id,"added")
};
const removeTodo = id => {
if (todos[id]) {
delete todos[id];
}
saveAndToggle(id,"deleted"); // toggle anyway
};
function createToDoInput() {
const todoContainer = document.createElement("div");
todoContainer.id = 'todo' + new Date().getTime(); // unique ID
const newToDoInputCheckbox = document.createElement("INPUT");
newToDoInputCheckbox.setAttribute("type", "checkbox");
const newToDoInput = document.createElement("INPUT");
const newXBtn = document.createElement("SPAN");
todoContainer.appendChild(newToDoInputCheckbox);
todoContainer.appendChild(newToDoInput);
todoContainer.appendChild(newXBtn);
newToDoInputCheckbox.classList.add("checkbox");
newToDoInput.classList.add("to-do-input");
newXBtn.classList.add("X");
newXBtn.innerHTML = "X";
toDoInputContainer.appendChild(todoContainer);
}
toDoInputContainer.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("X")) {
const parent = tgt.closest("div")
removeTodo(parent.id);
parent.remove();
}
});
toDoInputContainer.addEventListener("change", function(e) {
const tgt = e.target;
if (tgt.classList.contains("to-do-input")) {
const id = tgt.closest("div").id;
if (tgt.value === "") removeTodo(id);
else saveTodo(id, tgt.value);
}
});
document.getElementById("add").addEventListener("click", createToDoInput);
toggleSelDel(); // possibly show the select all button
document.getElementById("selAll").addEventListener("click", function() {
const checked = this.checked;
[...toDoInputContainer.querySelectorAll("[type=checkbox]")].forEach(chk => chk.checked = checked)
});
document.getElementById("delAll").addEventListener("click", function() {
[...toDoInputContainer.querySelectorAll("[type=checkbox]:checked")].forEach(chk => {
const parent = chk.closest("div");
removeTodo(parent.id);
parent.remove();
});
});
.hide { display: none; }
<button id="add">Add</button>
<div id="seldel" class="hide"><label>Select all<input type="checkbox" id="selAll"/></label><button type="button" id="delAll">Delete selected</button></div>
<div id="toDoInputContainer"></div>

Javascript - can't iterate over object in incremental search

I'm very new to javascript/dev so I hope there is a an obvious solution that I've not thought of. My code returns search items from TVMaze.com API. The feature giving me trouble is the incremental search (as a user types in input box, the code returns and displays images by creating a new div and appending images, removing and replacing the an div).
My problem is that on deleting all characters from input box, I receive the error: "Uncaught (in promise) TypeError: shows is not iterable" which I suppose means that there is no object to iterate over? Thanks in advance for any help.
const input = document.querySelector("#query");
input.addEventListener("input", async function (e) {
e.preventDefault();
const searchTerm = e.target.value;
const config = { params: { q: searchTerm } };
const res = await axios.get(`http://api.tvmaze.com/search/shows?`, config);
makeImages(res.data);
clearList();
});
const makeImages = (shows) => {
const div = document.createElement("div");
for (let result of shows) {
if (result.show.image) {
const img = document.createElement("IMG");
img.className += "resultImage";
img.src = result.show.image.medium;
const title = document.createElement("h3");
title.className += "resultTitle";
title.innerText = result.show.name;
const year = document.createElement("h4");
year.className += "score";
year.innerText = result.show.premiered;
var sub = year.innerText.substring(0, 4);
var yearNum = parseInt(sub);
div.append(year);
div.append(img);
div.append(title);
document.body.appendChild(div);
}
if (yearNum <= 2000) {
var retro = document.createElement("h5");
retro.className = "retro";
retro.innerText = "retro";
div.append(retro);
}
}
};
let clearList = () => {
var allImg = document.querySelectorAll("IMG");
if (allImg.length === 0) {
document.createElement("div");
return makeImages();
}
var oldDiv = document.querySelector("div");
oldDiv.remove();
console.log(oldDiv);
};

Keep Todo Results after browser refreshing

I created a todo app to add and remove tasks on the page.
however i would like to keep todo results when browser refreshed .
Is that possible to make this like storing data on db or any storage to save these results?
any idea to make this to save data ??
Now I posted the complete code hereee! because i cant posted code here before
let menu = document.querySelector(".bs");
let btn1 = document.querySelector(".btn");
let btn2 = document.querySelector(".btn3");
let irp = document.querySelector(".date");
let inp = document.querySelector(".input");
let bsd = document.querySelector(".sss");
let brs = document.querySelector(".marker");
let addBr = () => {
btn1.addEventListener("click", addBr);
let br = document.createElement("DIV");
let dd = document.createElement("H1");
dd.innerHTML = (inp.value);
br.className = "red";
var bn = document.createElement("H1");
bn.innerHTML = (irp.value);
menu.appendChild(br);
br.appendChild(dd);
br.appendChild(bn);
if( inp.value == "") {
br.remove();
}
else {
menu.appendChild(br);
}
if( irp.value == "") {
dd.innerHTML = "Albenis";
}
else {
menu.appendChild(br);
}
let ttt = document.createElement("BUTTON");
ttt.className = "marker";
ttt.innerHTML = "Remove";
br.appendChild(ttt);
// This is the important change. Part of creating the .ttt element
// is setting up its event listeners!
ttt.addEventListener('click', () => br.remove());
};
btn1.addEventListener("click", addBr);
// Call `addBr` once to add the initial element
addBr();
<html>
<body>
<div class="bs">
<input type="text" class="input">
<input type="date" class="date">
<button class="btn">
Add
</button>
</div>
</body>
</html>
TL;DR: use localStorage to read the items at page load and write the items when they change, like in the final version
To keep your todo entries, you need to store it in a Database. This can be either a local database in the website like localStorage. Or you need to build a backend which is connected to a Database and send and load the Data from there.
localStorage example:
const items = [{ name: "My Todo" }, { name: "My Todo 2" }];
const setItems = () => {
localStorage.setItem("items", JSON.stringify(items));
};
const getItems = () => {
return JSON.parse(localStorage.getItem("items"));
};
Including your code:
const getItems = () => {
return JSON.parse(localStorage.getItem("items"));
};
const items = getItems() || [];
const setItems = () => {
localStorage.setItem("items", JSON.stringify(items));
};
let addBr = (item) => {
let br = document.createElement("DIV");
let dd = document.createElement("H1");
dd.innerHTML = (item ? item.name : inp.value);
br.className = "red";
var bn = document.createElement("H1");
bn.innerHTML = (item ? item.name : irp.value);
if (!item) {
items.push({ name: inp.value });
setItems();
}
menu.appendChild(br);
br.appendChild(dd);
br.appendChild(bn);
if( inp.value == "") {
br.remove();
}
else {
menu.appendChild(br);
}
if( irp.value == "") {
dd.innerHTML = "Albenis";
}
else {
menu.appendChild(br);
}
let ttt = document.createElement("BUTTON");
ttt.className = "marker";
ttt.innerHTML = "Remove";
br.appendChild(ttt);
// This is the important change. Part of creating the .ttt element
// is setting up its event listeners!
ttt.addEventListener('click', () => br.remove());
};
for (const item of items) {
addBr(item);
}
btn1.addEventListener("click", () => addBr());

How do I create an edit function inside of a list?

Currently I have a delete function already which is shown by a cross
So how I am doing this is by using a function that renders in the information from another database, into this list.
function renderCafe(doc){
let li = document.createElement('li');
let name = document.createElement('span');
let city = document.createElement('span');
let cross = document.createElement('div');
li.setAttribute('data-id', doc.id);
name.textContent = doc.data().name;
city.textContent = doc.data().city;
cross.textContent = 'x';
li.appendChild(name);
li.appendChild(city);
li.appendChild(cross);
cafeList.appendChild(li);
// deleting data
cross.addEventListener('click', (e) => {
e.stopPropagation();
let id = e.target.parentElement.getAttribute('data-id');
db.collection('cafes').doc(id).delete();
});}
So how do I create the edit button function like this delete one? Should it also be an EventListener that occurs when clicked?
I was thinking to have an edit button, when clicked, changes into "Update", while the static information turns into a text box with the current values.
Then when the "Update" is being clicked, it then saves the information.
I am a student, and have no prior knowledge in javascript, i took these codes from tutorials that I can find online.
Here's a possible solution, similar to your style.
Replace the alert with a database update.
Make sure you're listening for document changes, and updating your UI accordingly, so that the new name and city will replace your old ones.
const cafeList = document.getElementById('cafe-list');
const sampleCafes = [
{ data: () => ({ name: 'new cafe', city: 'new city'}), id: 'sample-cafe' },
];
sampleCafes.forEach(cafe => renderCafe(cafe));
function renderCafe(doc){
let li = document.createElement('li');
let name = document.createElement('p');
let city = document.createElement('p');
let nameInput = document.createElement('input');
let cityInput = document.createElement('input');
let edit = document.createElement('div');
let submit = document.createElement('div');
let cross = document.createElement('div');
li.setAttribute('data-id', doc.id);
name.textContent = doc.data().name;
city.textContent = doc.data().city;
nameInput.value = name.textContent;
cityInput.value = city.textContent;
nameInput.hidden = true;
cityInput.hidden = true;
edit.textContent = 'edit';
submit.textContent = 'submit';
submit.hidden = true;
cross.textContent = 'x';
li.appendChild(name);
li.appendChild(city);
li.appendChild(nameInput);
li.appendChild(cityInput);
li.appendChild(edit);
li.appendChild(submit);
li.appendChild(cross);
cafeList.appendChild(li);
// deleting data
cross.addEventListener('click', (e) => {
e.stopPropagation();
let id = e.target.parentElement.getAttribute('data-id');
alert(`db.collection('cafes').doc(id).delete();`);
});
// editing data
edit.addEventListener('click', (e) => {
e.stopPropagation();
nameInput.hidden = false;
cityInput.hidden = false;
submit.hidden = false;
name.hidden = true;
city.hidden = true;
edit.hidden = true;
});
// submitting new data
submit.addEventListener('click', (e) => {
e.stopPropagation();
const id = e.target.parentElement.getAttribute('data-id');
nameInput.hidden = true;
cityInput.hidden = true;
submit.hidden = true;
name.hidden = false;
city.hidden = false;
edit.hidden = false;
const newName = nameInput.value;
const newCity = cityInput.value;
alert(`TODO: update doc '${id}' to\n{name: '${newName}', city: '${newCity}'}.`);
});
}
<ul id="cafe-list"></ul>

Local Storage issue

I'm trying to use local storage so that my invites stay on the page when refreshed. How would I go about implementing this into my code. I really don't know where to start and I'm really struggling with it. Please cans someone just show me how to implement this into my code. Ive been creating child elements and appending them to the UL in the HTML.
const form = document.getElementById("registrar");
const input = form.querySelector("input");
const mainDiv = document.querySelector(".main");
const ul = document.getElementById("invitedList");
const div = document.createElement('div');
const filterLabel = document.createElement('label');
const filterCheckBox = document.createElement('input');
filterLabel.textContent = "Hide those who havent responded";
filterCheckBox.type = 'checkbox';
div.appendChild(filterLabel);
div.appendChild(filterCheckBox);
mainDiv.insertBefore(div, ul);
/*
This creates a checkbox to see you has confirmed if they are coming
to the event or not.
*/
filterCheckBox.addEventListener("change", (e) => {
const isChecked = e.target.checked;
const lis = ul.children;
if (isChecked) {
for (let i = 0; i < lis.length; i += 1) {
let li = lis[i]
if (li.className === 'responded') {
li.style.display = '';
} else {
li.style.display = 'none';
}
}
} else {
for (let i = 0; i < lis.length; i += 1) {
let li = lis[i]
li.style.display = '';
}
}
});
/*
This function creates new list items (the invites).
*/
createLi = (text) => {
createElement = (elementName, property, value) => {
const element = document.createElement(elementName);
element[property] = value;
return element;
}
appendElement = (elementName, property, value) => {
const element = createElement(elementName, property, value);
li.appendChild(element);
return element;
}
const li = document.createElement("li");
appendElement("span", "textContent", text);
appendElement("label", "textContent", "Confirmed")
.appendChild(createElement("input", "type", "checkbox"));
appendElement("button", "textContent", "edit");
appendElement("button", "textContent", "remove");
return li;
}
}
form.addEventListener("submit", (event) => {
event.preventDefault();
const text = input.value;
input.value = "";
const li = createLi(text);
ul.appendChild(li);
});
ul.addEventListener("change", () => {
const checkbox = event.target;
const checked = checkbox.checked;
const listItem = checkbox.parentNode.parentNode;
if (checked) {
listItem.className = "responded";
} else {
listItem.className = "";
}
});
ul.addEventListener("click", (e) => {
if (e.target.tagName === 'BUTTON') {
const button = e.target;
const li = button.parentNode;
const ul = li.parentNode;
const action = button.textContent;
const nameActions = {
remove: () => {
ul.removeChild(li);
},
edit: () => {
const span = li.firstElementChild;
const input = document.createElement('input');
input.type = 'text';
input.value = span.textContent;
li.insertBefore(input, span);
li.removeChild(span);
button.textContent = 'Save';
},
Save: () => {
const input = li.firstElementChild;
const span = document.createElement('span');
span.textContent = input.value;
li.insertBefore(span, input);
li.removeChild(input);
button.textContent = 'edit';
}
};
nameActions[action]();
}
});
I only can give you an idea for this, if you are planning to save any big data to localStorage, you can save your data to string and remake it to JSON object!
Here's an exmaple for saving data set
var toSave = [ ];
var whatToSave = (Your invites data List, maybe a "text" var for your code?, organize
to array or loop for your "UL" tag)
for(var i=0;i<whatToSave.length;i++){
var obj = [];
obj[i] = {
text:whatToSave[i].text,
data1:whatToSave[i].data1,
data2:whatToSave[i].data2,
...
}
toSave.push(obj[i]);
}
var saveToString = JSON.stringify(toSave);
localStorage.setItem('invites', saveToString); //your invite data saved in local
storage
....
//after refreshing or when you need to use your saved data
var cameBack = JSON.parse(localStorage.getItem('invites'));
//this will return same data again
//and make function to make UL using retured data array
you don't really need to for loop and push if you already organized needed data to array, just wrote it to make you understand an idea to save data in localStorage. I don't know if this will help you but get an idea and implement it to your project :)

Categories