2

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";
}
2
  • that code is crying out for encapsulating the booking database logic to separate it from the UI logic. Commented Jan 2, 2021 at 10:28
  • I will look into that, thanks @Alnitak Commented Jan 2, 2021 at 10:35

1 Answer 1

2

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>
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you, I will go try this. My edit function has stopped working so I need to fix that first.
Unfortunately this makes no difference. I am not really understanding the .input:eq(0) part, could you explain?
You've two inputs fname and lname, the :eq will select them by index, try to add e.preventDefault() just after $("#edit").click(function (e) {
Thanks, I meant to add that earlier, still no luck though, throwing error: Cannot read property 'find' of undefined
Ok try var parent_form = $('#regForm'); or var parent_form = $(this).closest('form'); instead of var parent_form = $(this.form);
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.