I have a table with a button in each row that displays a form. Confirming the form always changes the first entry, regardless of clicked edit button

Viewed 138

I'll preface by saying I'm a complete noob here and this is part of a project for an online course. I am 99% sure that some of the code here is going to be either horribly formatted and/or against best practices.

Here is the relevant part of the HTML page with the table:

    <form action="/timers" method="post">
        <div class="form-group">
            <input id="newTimerName" autocomplete="off" autofocus class="form-control" name="newTimerName" placeholder="New Timer" type="text" onkeyup="enableButton()">
            <br>
        </div>
        <button id="submit" name="submit" class="btn btn-primary" type="submit" disabled>Add Timer</button>
    </form>
    <br>
    <table id="editTimers" name="editTimers" class="table table-striped">
        <thead class="thead-dark">
            <tr id="header_row">
               <th scope="col">
                   Edit
               </th>
               <th scope="col">
                   Timer
               </th>
               <th scope="col">
                   Total Time Elapsed
               </th>
               <th scope="col">
                   Delete
               </th>
            </tr>
        </thead>
        {% for timer in timers %}
            <tr id="row_{{ loop.index0 }}" name="row">
                <td id="edit_row_{{ loop.index0 }}" name="edit" scope="row">
                    <button class="btn btn-primary" id="edit_{{ loop.index0 }}" name="edit" onclick="openForm()">Edit</button>
                    <div class="form-popup" id="editForm">
                        <form action="/edit_timer" class="form-container" method="post">
                            <label for="oldTimerName"><b>{{ timer["timer"] }}</b></label>
                            <input hidden name="oldTimerName" value="{{ timer["timer"] }}">

                            <label for="changeTimerName"><b hidden>New Timer Name</b></label>
                            <input type="text" placeholder="New Timer Name" name="changeTimerName" required>

                            <button type="submit" class="btn" id="submit_edit_{{ loop.index0 }}" name="submitEdit">Edit</button>
                            <button class="btn cancel" id="cancel_{{ loop.index0 }}" name ="cancel"  onclick="closeForm()">Cancel</button>
                        </form>
                    </div>
                </td>
                <form action="/delete_timer" method="post">
                    <td id="timer_name_row_{{ loop.index0 }}" name="timer_name" scope="row">
                        <label for="inputTimerName">{{ timer["timer"] }}</label>
                        <input hidden id"inputTimerName" name="inputTimerName" value="{{ timer["timer"] }}">
                    </td>
                    <td id="total_time_row_{{ loop.index0 }}" name="total_time" scope="row">
                        {{ timer["total_time"] }}
                    </td>
                    <td id="delete_row_{{ loop.index0 }}" name="delete" scope="row">
                        <button id="delete_{{ loop.index0 }}" name ="delete" class="btn btn-primary" type="submit">Delete</button>
                    </td>
                </form>
            </tr>
        {% endfor %}
    </table>

The simple javascript to open and close the form:

function openForm() {
  document.getElementById("editForm").style.display = "block";
}

function closeForm() {
  document.getElementById("editForm").style.display = "none";
}

and the python file, using flask:

@app.route("/timers", methods=["GET", "POST"])
@login_required
def timers():
    """Manage Timers"""
    if request.method == "POST":

        # if adding new timer
        timerName = request.form.get("newTimerName")
        db.execute("INSERT INTO timers (user_id, timer) VALUES (:id, :timer)",
                    id=session["user_id"], timer=timerName)
        # then reload page

    timers = db.execute("SELECT * FROM timers WHERE user_id = :id", id=session["user_id"])
    for row in timers:
        row["total_time"] = formatTime(row["total_time"])
    return render_template("timers.html", timers=timers)

@app.route("/delete_timer", methods=["POST"])
@login_required
def delete_timer():
    """Delete Timer"""
    if request.method == "POST":
        timer = request.form.get("inputTimerName")
        db.execute("DELETE FROM timers WHERE user_id = :id AND timer = :timer",
                    id=session["user_id"], timer=timer)

    # reload page
    timers = db.execute("SELECT * FROM timers WHERE user_id = :id", id=session["user_id"])
    for row in timers:
        row["total_time"] = formatTime(row["total_time"])
    return render_template("timers.html", timers=timers)

@app.route("/edit_timer", methods=["POST"])
@login_required
def edit_timer():
    """Edit Timer"""
    if request.method == "POST":
        oldTimer = request.form.get("oldTimerName")
        newTimer = request.form.get("changeTimerName")
        db.execute("UPDATE timers SET timer = :newTimer WHERE user_id = :id and timer = :oldTimer", newTimer=newTimer, id=session["user_id"], oldTimer=oldTimer)

    # reload page
    timers = db.execute("SELECT * FROM timers WHERE user_id = :id", id=session["user_id"])
    for row in timers:
        row["total_time"] = formatTime(row["total_time"])
    return render_template("timers.html", timers=timers)

You'll see that in the for loop to display each row is a pop-up form that is linked to each edit button.

I assume the issue is that the pop-up form has a single id that stays the same regardless of which edit button is clicked. When they display, it shows the right text value so I'm not sure why it isn't submitting the corresponding value to the sql query. Regardless of edit/form button, the sql query always ends up with the first row's text value.

I would think that changing the ID to also include an indexed number would help, but then I'm not sure how to pass the indexed number to both the javascript and the flask file.

Any help would be greatly appreciated!

Thanks in advance.

0 Answers
Related