0

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>
7
  • You should focus on having a unique identifier for each appointment rather than basing it on first name / last name and their position in the array. When you edit a booking, the positions of the current elements in the array change, which is probably why your having problems. Commented Jan 3, 2021 at 9:23
  • I don't know how I would do that at all.. My deadline is in a few days and I have spent a week just getting to this point. I'm scared I will break the code more. The form is going to have a lot more elements too, I don't even know where I would start with that. Commented Jan 3, 2021 at 9:26
  • Would it be as simple as adding id: "uniqueID" to my array creation? I would then have to find a way to increment that on creation.. correct? @Shoejep Commented Jan 3, 2021 at 9:37
  • Essentially yes, from the code that you've provided, you can't add new appointments anyway, so you could just do { id: 1, fname: "John", lname: "Smith"} for e.g. then pass it to your #edit handler. If you save the code you have currently in a different file, then it can't get any worse by working on it. Commented Jan 3, 2021 at 9:46
  • You can add appointments using my code? I am able to create and delete currently, but not edit. It needs to automatically assign an id on submission of the booking, so that this can be retrieved to edit it later. None of this is hardcoded, I have an HTML form that sends the data to localStorage. Commented Jan 3, 2021 at 9:49

1 Answer 1

1

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")

Sign up to request clarification or add additional context in comments.

1 Comment

Oh amazing!! It works, I get you now about the Date() part, I wasn't sure where I was supposed to put it but that all makes sense. I knew it wasn't far off but I am terrible at knowing were to implement things. I also had no idea about data-id within the input, that will help me in the future. You've saved me, thank you.

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.