inputting the data is fine, submitting is fine. But, if I refresh, everything that was inputted displays as object object. Any idea's why?
In addition to this, each input creates table data but seperately rather than in a table and each input puts each newly created data side by side whereas I want them to space-around like justify-content: space-around. But it doesn't seem to be doing that
Still new to JS. I couldn't find exactly what i'm doing wrong. JSON stringify is still a new practice for me too. So, I am unsure if what I have done is correct.
EDIT ------------------------
Can anyone explain what is happening with the formatting after a refresh ?
html
<h1>Library</h1>
<div id="login" class="login-btn">
<button class="User" id = "login">login</button>
</div>
<button id="clear">Clear</button>
<form id="form" action="">
<input class="input" type="text" id="input-title" placeholder="Title" required />
<input class="input" type="text" id="input-author" placeholder="Author" required/>
<input class="input" type="number" id="input-number" placeholder="Pages" required />
<input value="Submit" id="submitbtn" class="submit" type="submit">
</form>
<input type="checkbox" class="checkbox"><span> Check me if you read the book</span>
<table id="table">
</table>
<script src="script.js"></script>
</body>
</html>
js
//buttons
const buttonLogin = document.getElementById("login")
const table = document.getElementById("table")
const clearBtn = document.getElementById("clear")
const submitBtn = document.getElementById("submitbtn")
const form = document.getElementById("form")
const inputTitle = document.getElementById("input-title")
const inputAuthor = document.getElementById("input-author")
const inputNumber = document.getElementById("input-number")
//array local storage
let itemsArray = localStorage.getItem('items')
? JSON.parse(localStorage.getItem('items'))
: []
localStorage.setItem('items', JSON.stringify(itemsArray))
const data = JSON.parse(localStorage.getItem('items'))
const createBook = (text, text1, text2) => {
const tble = document.createElement('table')
const td = document.createElement('td')
const td2 = document.createElement('td')
const td3 = document.createElement('td')
td.textContent = text
td.style.color = ('black')
td.style.border = ('solid')
td.style.borderColor =('blueviolet')
td2.textContent = text1
td2.style.color = ('black')
td2.style.border = ('solid')
td2.style.borderColor = ('blueviolet')
td3.textContent = text2
td3.style.color = ('black')
td3.style.border = ('solid')
td3.style.borderColor =('blueviolet')
table.appendChild(td)
table.appendChild(td2)
table.appendChild(td3)
}
form.addEventListener('submit', function (e) {
e.preventDefault()
//for (var i = 0; i < 2; i++) {
itemsArray.push(inputTitle, inputAuthor, inputNumber)
localStorage.setItem('items', JSON.stringify(itemsArray))
createBook(inputTitle.value, inputAuthor.value, inputNumber.value)
inputTitle.value = ''
inputAuthor.value= ''
inputNumber.value= ''
// }
})
data.forEach ((item) => {
createBook(item)
})
//clear list
clearBtn.addEventListener('click', function () {
localStorage.clear()
while (table.firstChild) {
table.removeChild(table.firstChild)
}
})
You need to save the values of the inputs, not the input elements themselves. And the values for a single item should be collected together into an array or object.
itemsArray.push([inputTitle.value, inputAuthor.value, inputNumber.value])
Also, when you process the data, you need to spread the array into separate arguments to createBook().
data.forEach ((item) => {
createBook(...item)
})
i think it's relate to this line
itemsArray.push(inputTitle, inputAuthor, inputNumber)
// where
const inputTitle = document.getElementById("input-title")
const inputAuthor = document.getElementById("input-author")
const inputNumber = document.getElementById("input-number")
// should be below if you don't want printout [object Object]
itemsArray.push(inputTitle.value, inputAuthor.value, inputNumber.value)
why '[object Object]'
var array = []
var anchor = document.createElement('a')
array.push(JSON.stringify(anchor)) // -> ['{}']
var anchor2 = document.createElement('a')
anchor2.textContent = JSON.parse('{}')
anchor2.textContent // -> '[object Object]'
Related
I've been trying to store an array from the the users input into localstorage and the output is not really encouraging as it gives inappropriate result:
<form action="index.php">
<input type="text" value=" " class="ex" >
<button id="ex">add item </button>
</form>
const items2 = document.querySelector('form');
items2.addEventListener('submit', function(ev) {
const items1 = document.getElementsByClassName('ex').value;
let items3;
if (localStorage.getItem('items3') === null) {
items3 = [];
} else {
items3 = JSON.parse(localStorage.getItem('items3'));
}
localStorage.setItem('items3', JSON.stringify(items3));
items3.push(items1);
alert('submit');
ev.preventDefault();
});
const items3 = JSON.parse(localStorage.getItem('items3'));
items3.forEach(function(items1) {
console.log(items1);
});
so, the problem I am facing exactly is that the alert always respond each time I click on the button which is but the localStorage file keeps giving the same value as an empty array [] regardless of any value I input into the text container. The forEach is also returning an error of
cannot read properties of an empty of null ('forEach')
The first time you run the script, nothing has been saved to local storage, so
const items3 = JSON.parse(localStorage.getItem('items3'));
will set items3 to null. That needs to have error checking to create a default value.
The submit listener needs to save to local storage after pushing the new item into the array.
There's no need to call localStorage.getItem() in the listener. You can just use the global items3 variable that's set when you read from local storage at the beginning.
const items2 = document.querySelector('form');
items2.addEventListener('submit', function(ev) {
const items1 = document.getElementsByClassName('ex').value;
items3.push(items1);
localStorage.setItem('items3', JSON.stringify(items3));
alert('submit');
ev.preventDefault();
});
const items3 = JSON.parse(localStorage.getItem('items3') || '[]');
items3.forEach(function(items1) {
console.log(items1);
});
<form action="index.php">
<input type="text" value=" " class="ex" >
<button id="ex">add item </button>
</form>
The reason you get null is because, document.getElementsByClassName('ex') returns a HTMLCollection. So, when you do document.getElementsByClassName('ex').value it doesn't contain a value but an object and then returns null; you'll need to iterate over it to retrieve values or specify an index, such as document.getElementsByClassName('ex')[0].value or better still, document.getElementById('ex').value
Here's a fix for you.
<form>
<input name="firstName" type="text" id="firstName" class="firstName" />
<button id="ex">add items</button>
</form>
const items2 = document.querySelector("form");
items2.addEventListener("submit", function (ev) {
ev.preventDefault();
let items1 = document.getElementById("firstName").value;
// or let items1 = document.getElementsByClassName("firstName")[0].value;
items3.push(items1);
localStorage.setItem("items3", JSON.stringify(items3));
document.getElementById("firstName").value = "";
alert("name added successfully")
});
const items3 = JSON.parse(localStorage.getItem("items3") || "[]");
items3.forEach(function (items1) {
console.log(items1);
});
I have a problem in Javascript.I am adding new list items to the 'ul' elements and this list is empty at first and I do not want to add same values twice. When I write the if statement I get the exception because my list is empty so the result return null.
How can I fix this this problem?
Thank you in advance...
Html Codes
<input type="text" id="the-filter" placeholder="Search For..." />
<div class="list-container">
<ul id="myList"></ul>
<button id="button">Click</button>
Javascript Codes
let newlist = document.querySelector("#myList");
const li = document.getElementsByClassName('list-group-item');
const button = document.getElementById("button");
const button.addEventListener('click' , listName);
const input = document.getElementById("the-filter");
function listName()
const inputVal = input.value;
for (i = 0; i < li.length; i++) {
if ((li[i].innerHTML.toLocaleLowerCase().includes(inputVal) && inputVal!="") ||
(li[i].innerHTML.toUpperCase().includes(inputVal) && inputVal!="")) {
let newItem = document.createElement("li");
li[i].classList.add("list-group-item");
let textnode = document.createTextNode(li[i].innerHTML.toLocaleLowerCase());
newItem.appendChild(textnode);
if((newlist.children[0].innerHTML.toLocaleLowerCase().includes(inputVal))){
newlist.insertBefore(newItem, newlist.childNodes[0]);
}
}
}
}
If I understood the task correct, you need to add items to the list by button click.
If same item exists (case insensitive), then nothing happens.
const list = document.querySelector("#myList");
const button = document.getElementById("button");
button.addEventListener("click", listName);
const input = document.getElementById("the-filter");
function listName() {
const inputVal = input.value;
const [...lis] = document.getElementsByClassName("list-group-item");
const same = lis.find((el) => el.textContent.toLowerCase() === inputVal.toLowerCase());
if (same) {
return;
}
let newItem = document.createElement("li");
newItem.classList.add("list-group-item");
newItem.textContent = inputVal;
list.appendChild(newItem)
}
<input type="text" id="the-filter" placeholder="Search For..." />
<div class="list-container">
<ul id="myList"></ul>
<button id="button">Click</button>
</div>
You're on the right track with event listeners and element creation, but your original code didn't quite seem to match your stated goal.
Here's a solution you might find useful, with some explanatory comments:
// Identifies some DOM elements
const
input = document.getElementById("my-input"),
newList = document.getElementById("my-list"),
items = document.getElementsByClassName('list-group-item'),
button = document.getElementById("my-button");
// Focuses input, and calls addItem on button-click
input.focus();
button.addEventListener('click', addItem);
// Defines the listener function
function addItem(){
// Trims whitespace and sets string to lowerCase
const inputTrimmedLower = input.value.trim().toLocaleLowerCase();
// Clears and refocuses input
input.value = "";
input.focus();
// Ignores empty input
if (!inputTrimmedLower) { return; }
// Ignores value if a list item matches it
for (const li of items) {
const liTrimmedLower = li.textContent.trim().toLocaleLowerCase();
if (liTrimmedLower === inputTrimmedLower) {
console.log(`${inputTrimmedLower} is already listed`);
return;
}
}
// If we got this far, we want to add the new item
let newItem = document.createElement("li");
newItem.classList.add("list-group-item");
newItem.append(inputTrimmedLower); // Keeps lowerCase, as your original code
newList.prepend(newItem); // More modern method than `insertBefore()`
}
<input id="my-input" />
<ul id="my-list"></ul>
<button id="my-button">Click</button>
I have the following code that need to display the id,name and occupation. i can add to local storage but need to display it in table and sort based on name, id and occupation. any idea how can i do it using javascript. sample outputoutput
<!DOCTYPE html>
<html>
<title>Sorting Test</title>
<body>
<fieldset>
<legend>Add participant<legend>
<input id="userID" type="text">
<input id="userName" type="text">
<input id="userOccupation" type="text">
<button id="addbtn" type="button" >Add</button>
</fieldset>
<br>
<div id="displayOutput">
</div>
</body>
<script>
// get the userid, userName and UserOccupation
const userID = document.getElementById("userID");
const userName = document.getElementById("userName");
const userOccupation = document.getElementById("userOccupation");
const addbtn = document.getElementById("addbtn");
const displayOutput = document.getElementById("displayOutput");
//add user input to storage
addbtn.onclick = function(){
const id = userID.value;
const name = userName.value;
const occupation = userOccupation.value;
if(id && name && occupation)
{
let myObj = {
id,
name,
occupation
};
let myObj_serialized = JSON.stringify(myObj);
localStorage.setItem("myObj",myObj_serialized);
}
//view the stored information
for (let i=0; i < localStorage.length; i++)
{
const key = localStorage.key(i);
const value =localStorage.getItem(key);
var row = `<tr><td>${key}: ${value}<td><tr><br/>`;
displayOutput.innerHTML += row;
console.log(value);
}
};
</script>
</html>
You are overriding the stored item values everytime you call setItem. If you want to display a table, I suggest storing an array of objects. If you want to use local storage, Stringify the array before storing and parse it when you need to read it
var storeData = function(data) {
localStorage.setItem("tableData",JSON.stringify(data);
}
storeData([]);
var getData = function() {
return JSON.parse(localStorage.getItem("tableData"));
}
And call something like this to save data:
storeData(getData().push({id: id, name: name, occupation: occupation});
And then to display the data you can do:
var arr = getData();
arr.forEach(element) {
displayOutput.innerHtml += `
<tr>
<td>ID: ${element.id}</td>
<td>Name: ${element.name}</td>
<td>Occupation: ${element.occupation}</td>
</tr>`;
}
As for the sorting, you can call a sort function on the array on the onclick of the table's column header.
I just started learning javascript. Today trying to learn Map Object Key and Value Pairs. but somehow I see a nonfunctional method of Map namely clear().
whole code I posted below. and line34 and line36 prints same map pairs albeit map object clear method already invoked. where am I wrong ? I just wanna clear the Map object named list_
here is a link you can test and see weirdness: https://codepen.io/KTURKAY/pen/oEpXgb
var list_ = new Map();
var inputkey;
var inputvalue;
var buttonadd;
var buttonclear;
var divlist;
function buttonclearclick(el, ev) {
divlist.innerHTML = '';
console.log(list_);
list_.clear();//I expected, this method should clear it. but indeed it doesn't.?
console.log(list_);
}
function buttonaddclick(c, e) {
list_[inputkey.value] = inputvalue.value;
divlist.innerHTML = "";
for (x in list_) {
let n = document.createElement('div');
n.innerHTML = `${x} = ${list_[x]}`;
divlist.appendChild(n);
}
}
document.body.onload = function(ev) {
inputkey = document.getElementById('inputkey');
inputvalue = document.getElementById('inputvalue');
buttonadd = document.getElementById('buttonadd');
buttonclear = document.getElementById('buttonclear');
divlist = document.getElementById('divlist');
buttonadd.addEventListener('click', buttonaddclick);
buttonclear.addEventListener('click', buttonclearclick);
}
<form>
KEY:
<input type="text" id="inputkey" /> VALUE:
<input type="text" id="inputvalue" />
<input type="button" value="ADD" id="buttonadd" />
<input type="button" value="CLEAR" id="buttonclear" />
</form>
<div id="divlist">
NO DATA
</div>
Some issues:
The items are retrieved in the wrong way from the map. Use the .get method.
The items are not iterated in the correct way. Use for ... of instead of for ... in
See updated script running correctly in this snippet. Comments indicate the corrections:
var list_ = new Map();
var inputkey;
var inputvalue;
var buttonadd;
var buttonclear;
var divlist;
function buttonclearclick(el, ev) {
divlist.innerHTML = '';
console.log('before: ' + list_.size); // To make it work in this snippet
list_.clear();
console.log('after: ' + list_.size); // To make it work in this snippet
}
function buttonaddclick(c, e) {
list_.set(inputkey.value, inputvalue.value); // Use set
divlist.innerHTML = "";
for (const [key, value] of list_) { // Get entries using `of`
const n = document.createElement('div');
n.textContent = `${key} = ${value}`; // Use pair coming from iterator
divlist.appendChild(n);
}
}
document.body.onload = function (ev) {
inputkey = document.getElementById('inputkey');
inputvalue = document.getElementById('inputvalue');
buttonadd = document.getElementById('buttonadd');
buttonclear = document.getElementById('buttonclear');
divlist = document.getElementById('divlist');
buttonadd.addEventListener('click', buttonaddclick);
buttonclear.addEventListener('click', buttonclearclick);
}
<form>
KEY:
<input type="text" id="inputkey" /> VALUE:
<input type="text" id="inputvalue" />
<input type="button" value="ADD" id="buttonadd" />
<input type="button" value="CLEAR" id="buttonclear" />
</form>
<div id="divlist">
NO DATA
</div>
The problem is this:
list_[inputkey.value] = inputvalue.value;
You need to use get and set to work with Maps:
list_.set(inputkey.value, inputvalue.value);
Calling clear() does remove all key/values from the internal Maps Hashmap, but it does not clear the object properties. And if you use the first way of setting properties, you dont actually need a Map but you can use a plain object.
Like if I have these two input boxes.
<input type="button" id="valone">
<input type="button" id="valuetwo">
<button type="submit" onClick="submitB();" id="sbmtbtn">
<script>
const firstval = findViewById="valueone";
const secondval = findViewById="valuetwo";
const submit = findViewById="sbmtbtn";
const first = firstval.value;
const second = secondval.value;
function submitB() {
const firebaseRef = firebase.database().ref().push();
firebaseRef.child("Value").child("Value One").set(first.value);
firebaseRef.child("Value").child("Value Two").set(second.value);
}
But it does this image like .......
It shows blanks not the values of the input box
Please help me all dependencies are set upped correctly and everything is pretty fine.
You're trying to look up the HTML elements, but are using a non-existing function. You're looking for getElementById(), like this:
<input type="button" id="valone">
<input type="button" id="valuetwo">
<button type="submit" onClick="submitB();" id="sbmtbtn">
<script>
const firstElm = findElementById("valueone");
const secondElm = findElementById("valuetwo");
const submitBtn = findElementById("sbmtbtn");
const first = firstElm.value;
const second = secondElm.value;
function submitB() {
const firebaseRef = firebase.database().ref().push();
firebaseRef.child("Value").child("Value One").set(first);
firebaseRef.child("Value").child("Value Two").set(second);
}