Double Square Brackets in my Javascrip Arrays within localStorage? - javascript

I have managed to get data registering to my localStorage as arrays, however I have three queries:
Why are there double square brackets around my array?
How do I change the name field to the respective html ID?
Data returning as undefined when I try to retrieve it from the localStorage?
The output I am looking for in my localStorage is:
bookings: [
[0]{fname: "John", lname: "Smith" }
[1]{fname: "Jane", lname: "Doe" }
]
But I am currently getting:
bookings: [
[0][{name: "fname" value: "John"},{name: "lname": value: "Smith" }]
[1][{name: "fname" value: "Jane"},{name: "lname": value: "Doe" }]
]
I understand how to change the name value when items are hardcoded but I am initialising an empty array in my JS and not sure where the error is, I have tried assigning a value to the array [0] but then it doesn't register anything. I have also tried the data.flat() method which does nothing.
The issue is my next step is to amend and delete items so I need to try and understand the structure. Currently I am getting undefined when I try to get data from storage, I have provided my remove function (currently to show) below, I know it is wrong but I think the issue is to do with how I am storing the data. Sorry I have asked so many questions on this but I am new to JS and still learning. I am struggling with searches as there are so many variations of Javascript and getting a lot of answers relating to C# or Python which isn't helping.
Here is my code:
//var bookings = [];
var bookings = localStorage.getItem("bookings");
$("#submit").click(function () {
//bookings = JSON.parse(localStorage.getItem("bookings")) || [];
bookings = (bookings) ? JSON.parse(bookings) : [];
var newBooking = $("#regForm").serializeArray();
bookings.push(newBooking)
var json = JSON.stringify(bookings);
const newData = bookings.flat();
window.localStorage.setItem("bookings", json);
});
$("#remove").click(function () {
var strBookings;
var i;
strBookings = localStorage.getItem("bookings");
//document.write("<p>" + strBookings + "</p>");
bookings = JSON.parse(strBookings);
for (i = 0; i < strBookings.length; i++) {
document.write("<p>" + strBookings[i].value + "</p>");
}
//localStorage.removeItem('bookings');
});
Form
<form id="regForm" name="regForm" class="col-sm-6">
<div class="row">
<input type="text" id="fname" placeholder="First Name" name="fname" required>
<input type="text" id="lname" placeholder="Last Name" name="lname" required>
<input id="submit" type="submit" value="Submit">
</div>
</form>
Show
//var bookings = [];
var bookings = localStorage.getItem("bookings");
$("#submit").click(function () {
//bookings = JSON.parse(localStorage.getItem("bookings")) || [];
bookings = (bookings) ? JSON.parse(bookings) : [];
var newBooking = $("#regForm").serializeArray();
bookings.push(newBooking)
var json = JSON.stringify(bookings);
const newData = bookings.flat();
window.localStorage.setItem("bookings", json);
});
$("#remove").click(function () {
var strBookings;
var i;
strBookings = localStorage.getItem("bookings");
//document.write("<p>" + strBookings + "</p>");
bookings = JSON.parse(strBookings);
for (i = 0; i < strBookings.length; i++) {
document.write("<p>" + strBookings[i].value + "</p>");
}
//localStorage.removeItem('bookings');
});
<form id="regForm" name="regForm" class="col-sm-6">
<div class="row">
<input type="text" id="fname" placeholder="First Name" name="fname" required>
<input type="text" id="lname" placeholder="Last Name" name="lname" required>
<input id="submit" type="submit" value="Submit">
</div>
</form>
<button id="remove" value="Remove">Show</button>

Related

Updating an Object in LocalStorage Using JavaScript?

Edit - Updated JS code to display suggestions made in comments, still having issues.. Now the button <input id="edit" type="submit" value="Submit"> won't go to edit.html, instead it is returning action.html? It is nested inside of the editForm?
I have a simple form which I have managed to learn to submit, add, remove, and display bookings using the localStorage (thanks to those who helped on here!).
My last task is to amend a booking, I think I am almost there with it, but not sure how to call the indexes (excuse my jargon), to replace the values.
The form submits and the web address reads something like edit.html?OldFirstName=NewFirstName&OldLastName=NewLastName, however the values don't update in storage, and it throws an error saying
Uncaught TypeError: Cannot read property 'fname' of undefined`.
I expected this to happen as I know I am not finding the values correctly, but I can't figure out how I should be writing it out? My thought process was that it would be similar to the original submit function but with the [i] values for fname and lname?
Here's my JS code - if you need anything else from me let me know:
// ~~~ add bookings to localStorage
var bookings = localStorage.getItem("bookings");
$("#submit").click(function () {
bookings = (bookings) ? JSON.parse(bookings) : [];
var newBookings = {
fname: $('#fname').val(),
lname: $('#lname').val()
}
bookings.push(newBookings);
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
});
// ~~~ edit bookings in localStorage
$("#edit").click(function (e) {
e.preventDefault();
bookings = (bookings) ? JSON.parse(bookings) : [];
var parent_form = $('#editForm');
var fname = parent_form.find('.input:eq(0)').val();
var lname = parent_form.find('.input:eq(1)').val();
var newBookings = {
fname: fname,
lname: lname
}
bookings.push(newBookings);
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
});
// ~~~ display bookings in browser
function showBooking(i) {
var bookingResult = document.getElementById("result");
var ul = document.createElement("ul");
var bookingItems = JSON.parse(localStorage.getItem("bookings")) || [];
bookingResult.innerHTML = "";
for (let i = 0; i < bookingItems.length; i++) {
bookingResult.innerHTML += `<div class="card card-body bg-light m-4">
<h3>${bookingItems[i].fname + " " + bookingItems[i].lname}
<button onclick="deleteBooking(${i})" class="btn btn-danger text-light ">Delete</button>
<button onclick="editBooking(${i})" class="btn btn-danger text-light ">Edit</button>
</h3>
</div>`;
}
}
// ~~~ edit bookings in browser
function editBooking(i) {
var bookingResult = document.getElementById("editAppt");
var bookingItems = JSON.parse(localStorage.getItem("bookings")) || [];
bookingResult.innerHTML =
`<form id="editForm" name="editForm" onsubmit="return editForm(this)" class="col-sm-6">
<div class="row">
<input type="text" class="input" id="fname_${i}" placeholder="${bookingItems[i].fname}" name="${bookingItems[i].fname}" required>
<input type="text" id="lname_${i}" class="input" placeholder="${bookingItems[i].lname}" name="${bookingItems[i].lname}" required>
<input id="edit" type="submit" value="Submit">
</div>
</form>`;
}
// ~~~ delete bookings from localStorage
function deleteBooking(i){
var bookingItems = JSON.parse(localStorage.getItem("bookings"));
bookingItems.splice(i, 1);
localStorage.setItem("bookings", JSON.stringify(bookingItems));
showBooking();
}
// ~~~ form submit handlers
function setAction(form) {
form.action = "action.html";
}
function editForm(form) {
form.action = "edit.html";
}
I can see that the issue comes from this like :
$("#edit").click(function (i) {
You expect the click event to return an index but it's not, the i will represent the event object, so you may need to use $(this) to get the related inputs like :
$("#edit").click(function (e) {
var parent_form = $(this.form);
var fname = parent_form.find('.input:eq(0)').val();
var lname = parent_form.find('.input:eq(1)').val();
....
NOTE: The id must not be duplicated, so you need to avoid that, you may use prefix like:
<input type="text" class="input" id="fname_${i}" placeholder="${bookingItems[i].fname}" name="${bookingItems[i].fname}" required>
<input type="text" class="input" id="lname_${i}" placeholder="${bookingItems[i].lname}" name="${bookingItems[i].lname}" required>

Updating a localStorage Item Using JavaScript/jQuery?

I am sorry to keep asking this question but I am really struggling with it and I cannot figure out what is going wrong, I have read countless SO pages and general internet searches with no luck. A few people have helped me on here but the values are updating incorrectly so I thought it would be best to ask a fresh question with my most recent trials.
The challenge is to create a client-side (only) mock dog walking application based on localStorage, I so far am able to add, delete, and view appointments in the browser. I also have an edit function set up, however when I hit submit (#edit), the value at position [x] (end index) updates no matter which index I try to edit. Here is an example of my stored arrays in localStorage under key 'bookings':
[0]{fname: "John", lname: "Smith"}
[1]{fname: "Jane", lname: "Doe"}
[2]{fname: "David", lname: "Miller"}
When I hit edit on John Smith, for example, it will replace the values of David Miller, rather than Johns details. I thought of trying to find the index of each person similar to what I have done when finiding the values to display in HTML (bookings[i].lname), however this throws an error saying that i cannot be used before initialisation (makes sense, but not sure how to work around it).
Here is my most recent JS:
// ~~~ add bookings to localStorage
var bookings = JSON.parse(localStorage.getItem("bookings")) || [];
window.onload = showBooking();
$("#submit").click(function() {
var newBookings = {
fname: $('#fname').val(),
lname: $('#lname').val()
}
bookings.push(newBookings);
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
showBooking();
});
// ~~~ edit bookings in localStorage
$(document).on('click','#edit',function (e) {
e.preventDefault();
var parent_form = $(this.form);
var fname = parent_form.find('.input:eq(0)').val();
var lname = parent_form.find('.input:eq(1)').val();
const i = bookings.findIndex(booking => bookings.fname == fname && bookings.lname == lname);
deleteBooking(i);
bookings.push({
fname,
lname
});
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
// showBooking();
});
// ~~~ display bookings in browser
function showBooking() {
var bookingResult = document.getElementById("result");
var ul = document.createElement("ul");
bookingResult.innerHTML = "";
for (let i = 0; i < bookings.length; i++) {
bookingResult.innerHTML += `<div class="card card-body bg-light m-4">
<h3>${bookings[i].fname + " " + bookings[i].lname}
<button onclick="deleteBooking(${i})" class="btn btn-danger text-light ">Delete</button>
<button onclick="editBooking(${i})" class="btn btn-danger text-light ">Edit</button>
</h3>
</div>`;
}
}
// ~~~ edit bookings in browser
function editBooking(i) {
// $('#regForm').hide();
$('#result').hide();
var currentItem = document.getElementById("currentItem");
var editBooking = document.getElementById("editAppt");
currentItem.innerHTML += `<div class="card card-body bg-light m-4">
<h3>${bookings[i].fname + " " + bookings[i].lname} </h3>
</div>`;
editBooking.innerHTML = `<input type="text" class="input" id="fname_${i}" placeholder="${bookings[i].fname}" name="${bookings[i].fname}" value="${bookings[i].fname}" required>
<input type="text" class="input" id="lname_${i}" placeholder="${bookings[i].lname}" name="${bookings[i].lname}" value="${bookings[i].lname}" required>
<input id="edit" type="submit" value="Edit">`;
}
// ~~~ delete bookings from localStorage
function deleteBooking(i) {
bookings.splice(i, 1);
localStorage.setItem("bookings", JSON.stringify(bookings));
showBooking();
}
My form for creating an appointment (this changes when editBooking is called):
<form id="regForm" name="regForm" action="" class="col-sm-6">
<div id="editAppt" class="row">
<input type="text" class="input" id="fname" placeholder="First Name" name="fname" required>
<input type="text" class="input" id="lname"placeholder="Last Name" name="lname" required>
<input id="submit" type="submit" value="Submit">
</div>
</form>
You need to assign a unique identifier to each appointment. This will help fix your problem as you are currently identifying appointments by their first name, last name and position in the array.
When you edit an appointment, it removes it from its current position and adds it at the end which changes the index of all the current elements leading to your problem.
This would also cause problems if you had two appointments with the same name.
For a unique identifier, I suggest using new Date().getTime() for now.
var newBookings = {
id: new Date().getTime(),
fname: $('#fname').val(),
lname: $('#lname').val()
}
Once you've assigned a unique identifier to each appointment, you can change your Edit button so that it looks like this:
<input data-id="${bookings[i].id}" id="edit" type="submit" value="Edit">
Then in your Edit event handler, change the bottom part so that it looks like this:
let i = bookings.findIndex(booking => booking.id == $(this).data("id"));
bookings[i].fname = fname;
bookings[i].lname = lname;
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
So to explain, assign a unique identifier to each appointment, store the id in the data-id attribute, retrieve the data-id, find the index of the appointment with that id, update the appointment properties, save the bookings.
If you also want to improve the readability of your code, I suggest not mixing vanilla JavaScript and jQuery, i.e. document.getElementById("result") could be $("#result")

Just trying out to check whether the value is present in array or not

I am trying to write a function in jQuery.
var arr1 = ["Jcob", "Pete", "Fin", "John"];
var str = $("#fname").val();
if (jQuery.inArray(str, arr1))
$("#lname").text("Bob");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="fname" name="fname">
<input type="text" id="lname" name="lname">
Please check my fiddle here
What it will do it the user will give the value in the first input box the jQuery function will check if the value is present in that array it will fill the second input box with the given text.
Three things:
You need to add an event listener to the first input to constantly keep checking when someone inputs something.
Before selecting elements in the DOM, make sure the DOM is ready.
You don't need jQuery at all here. Like most things, very easy to do without jQuery.
const names = [ "Jcob", "Pete", "Fin", "John" ];
document.addEventListener('DOMContentLoaded', function() {
const fname = document.getElementById('fname');
const lname = document.getElementById('lname');
fname.addEventListener('input', function(event) {
lname.value = names.includes(fname.value) ? 'Bob' : '';
});
});
<input type="text" id="fname" name="fname">
<input type="text" id="lname" name="lname">
If you insist on jQuery (which I do strongly recommend you shouldn't until you are proficient with the native DOM API):
const names = [ "Jcob", "Pete", "Fin", "John" ];
$(document).ready(function() {
const $fname = $('#fname');
const $lname = $('#lname');
$fname.on('input', function(event) {
if ($.inArray($fname.val(), names) > -1) {
$lname.val('Bob');
} else {
$lname.val('');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="fname" name="fname">
<input type="text" id="lname" name="lname">
Try this:
<body>
<input type="text" id="fname" name="fname">
<input type="text" id="lname" name="lname">
<button onclick="checkValue()">Click</button>
<script>
var arr1 = ["Jcob", "Pete", "Fin", "John"];
function checkValue() {
var str = $("#fname").val();
var val = jQuery.inArray(str, arr1);
if (val === -1) {
console.log("no value");
}
else {
$("#lname").val("Bob");
}
}
</script>
</body>

Trying to display object properties stored within an array onto a <ul> element

I've just started learning JS and I'm trying to do some basic projects to cement what I've learned from reading and courses and tutorials and whatnot. I'm trying to make a contact list which takes 4 inputs: first name, last name, email and phone number. I wrote this part already and passed the arguments into an object within an array. What I can't figure out is how to display the contact object. I want to try and print each property into a list item within an unordered list but I'm stuck here, either because I don't know enough about DOM manipulation or just because I'm not looking in the right direction
//this passes the text input as an object to the list array
var contactList = {
list: [],
addNew: function() {
this.list.push({
firstName: document.getElementById('firstname').value,
lastName: document.getElementById('lastname').value,
email: document.getElementById('emailAdd').value,
phoneNumber: document.getElementById('phoneNumber').value
});
},
};
// this runs the addNew() function and clears the input fields afterwards
var handlers = {
addContact: function() {
contactList.addNew();
document.getElementById('firstname').value = '';
document.getElementById('lastname').value = '';
document.getElementById('emailAdd').value = '';
document.getElementById('phoneNumber').value = '';
// view.displayContact();
},
};
//this is where i'm trying to display the contacts array
var view = {
displayContact: function() {
var contacts = document.getElementById('contactul');
for (var i = 0; i < contactList.list.length; i++) {
var li = document.createElement('li');
contacts.appendChild(li);
li.innerHTML += contactList.list[i];
};
},
};
<form>
First name:<br>
<input id="firstname" type="text" name="firstname">
<br> Last name:<br>
<input id="lastname" type="text" name="lastname">
<br> Email Address:<br>
<input id="emailAdd" type="text">
<br> Phone number:<br>
<input id="phoneNumber" type="text">
<br>
</form>
<button onclick='handlers.addContact()'>Submit</button>
<div id='displayContacts'>
<ul id='contactul'>
</ul>
</div>
This is the desired result. I just can't figure out how to write it.
Well, you're close. The problem you have here is that when you go to display your items, you have to get the values for each individual element (first name, last name, etc). You can do that through another loop, or just hard-code each one since there are only 4. Here is an example:
//this passes the text input as an object to the list array
var contactList = {
list: [],
addNew: function() {
this.list.push({
firstName: document.getElementById('firstname').value,
lastName: document.getElementById('lastname').value,
email: document.getElementById('emailAdd').value,
phoneNumber: document.getElementById('phoneNumber').value
});
},
};
// this runs the addNew() function and clears the input fields afterwards
var handlers = {
addContact: function() {
contactList.addNew();
document.getElementById('firstname').value = '';
document.getElementById('lastname').value = '';
document.getElementById('emailAdd').value = '';
document.getElementById('phoneNumber').value = '';
view.displayContact();
},
};
//this is where i'm trying to display the contacts array
var view = {
displayContact: function() {
var contacts = document.getElementById('contactul');
while(contacts.firstChild ){
contacts.removeChild(contacts.firstChild );
}
for (var i = 0; i < contactList.list.length; i++) {
var liForFirstName = document.createElement('li');
contacts.appendChild(liForFirstName);
liForFirstName.innerHTML += "First Name: " + contactList.list[i].firstName;
var liForLastName = document.createElement('li');
contacts.appendChild(liForLastName);
liForLastName.innerHTML += "Last Name: " + contactList.list[i].lastName;
var liForEmail = document.createElement('li');
contacts.appendChild(liForEmail);
liForEmail.innerHTML += "Email: " + contactList.list[i].email;
var liForPhoneNumber = document.createElement('li');
contacts.appendChild(liForPhoneNumber);
liForPhoneNumber.innerHTML += "Phone Number: " + contactList.list[i].phoneNumber;
};
},
};
<form>
First name:<br>
<input id="firstname" type="text" name="firstname">
<br> Last name:<br>
<input id="lastname" type="text" name="lastname">
<br> Email Address:<br>
<input id="emailAdd" type="text">
<br> Phone number:<br>
<input id="phoneNumber" type="text">
<br>
</form>
<button onclick='handlers.addContact()'>Submit</button>
<div id='displayContacts'>
<ul id='contactul'>
</ul>
</div>

How to convert the input name dot to json format in simple way?

I have used the struts json plugin and tried to convert the form data to json format to submit by ajax.
I have two cases in the HTML
<form>
<input type="text" name="user.name" value="Tom"></p>
<input type="text" name="user.location" value="China"></p>
<input type="text" name="user.data[0].id" value="993"></p>
<input type="text" name="user.data[0].accountId" value="123"></p>
<input type="text" name="user.data[1].id" value="222"></p>
<input type="text" name="user.data[1].accountId" value="333"></p>
</form>
What I expected is to convert it to the json structure:
{
user : {
name: "Tom",
location : "China",
data: [
{
id : 993,
accountId : 123
},
{
id : 222,
accountId : 333
}
]
}
}
I know how to declare the json data and declare the attributes one by one.
I would like to have the better way to make each form to be in json format using simple way rather than declaring the parameter one by one in json format.
Appreciate for any suggestion or advice. Thank you.
Provided your form is exactly like that
Using a plain JS approach
<form class="userform">
<input type="text" class="username" value="Tom"></p>
<input type="text" class="userlocation" value="China"></p>
<input type="text" class="userid" value="993"></p>
<input type="text" class="useraccountid" value="123"></p>
<input type="text" class="userid2" value="222"></p>
<input type="text" class="useraccountid2" value="333"></p>
</form>
Then assign the values to the object
var frm = document.getElementsByClassName('userform');
//initialize blank object and keys
var user = {},
user.name = "",
user.location = "",
user.data = [];
//get all child input elements
for(var i = 0; i < frm.length; i++){
var uname = frm[i].getElementsByClassName('username')[0];
var uloc = frm[i].getElementsByClassName('userlocation')[0];
var uid = frm[i].getElementsByClassName('userid')[0];
var uaccid = frm[i].getElementsByClassName('useraccountid')[0];
var uid = frm[i].getElementsByClassName('userid2')[0];
var uaccid = frm[i].getElementsByClassName('useraccountid2')[0];
//assign values to object here
user[name] = {}; //assigning a parent property here, the name for example.
user[name].name = uname.value;
user[name].location = uloc.value;
user[name].data.push({
'id': uid.value
'accountId': uaccid.value
});
user[name].data.push({
'id': uid2.value
'accountId': uaccid2.value
});
}
JSON.stringify(user); //convert to JSON (or ignore if you want a plain object)
Output would be this in JSON format
{
user :{
Tom: {
name: "Tom",
data: [
{
id : 993,
accountId : 123
},
{
id : 222,
accountId : 333
}
]
},
Jerry: {
//more data
},
Courage: {
//more data
}
}
}
Hope this helps
If your input fields are many, like id3, accountid3, 4, 5, 6. You have to loop through the classes that you assign to these two repetitive fields
Here you go with a solution using jQuery https://jsfiddle.net/pnz8zrLx/2/
var json = {};
$('button').click(function(){
$('form').each(function(i){
json["user" + i] = {};
json["user" + i].data = [];
var tempJSON = {};
$('form:nth-child(' + (i+1) + ') input[type="text"]').each(function(){
if($(this).attr('name') === 'name' || $(this).attr('name') === 'location'){
json["user" + i][$(this).attr('name')] = $(this).val();
} else {
tempJSON[$(this).attr('name')] = $(this).val();
if(tempJSON != {} && $(this).attr('name') === 'accountId'){
json["user" + i].data.push(tempJSON);
tempJSON = {};
}
}
});
});
console.log(json);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" name="name" value="Tom">
<input type="text" name="location" value="China">
<input type="text" name="id" value="993">
<input type="text" name="accountId" value="123">
<input type="text" name="id" value="222">
<input type="text" name="accountId" value="333">
</form>
<form>
<input type="text" name="name" value="Test">
<input type="text" name="location" value="Test112">
<input type="text" name="id" value="22">
<input type="text" name="accountId" value="78">
<input type="text" name="id" value="00">
<input type="text" name="accountId" value="44">
</form>
<button>
Submit
</button>
Hope this will help you.

Categories

Resources