Skip to content
Advertisement

Value of hidden field undefined when submitted after creation using javascript

I’m using Django and trying to get javascript to add a hidden field and then pass it to a view try to process the value.

When I hard code the hidden field using the following in my template:

<form action="{% url 'add_hamper' hamper_id=hamper.slug %}" method="post" novalidate id="form">
    {% csrf_token %}
    <input type="hidden" name="option_id" id="option_element" value="85">
    <button type="submit" class="btn btn-sm btn-success" id="price_button" data-price="{{ hamper.sale_price }}">{{ hamper.sale_price }}</button>
</form>

Everything works and I can see the value of the option_id in my view:

<QueryDict: {'csrfmiddlewaretoken': ['XXXX'], 'option_id': ['85']}>

However, when I start with the following HTML:

<form action="{% url 'add_hamper' hamper_id=hamper.slug %}" method="post" novalidate id="form">
    {% csrf_token %}
    <button type="submit" class="btn btn-sm btn-success" id="price_button" data-price="{{ hamper.sale_price }}">{{ hamper.sale_price }}</button>
</form>

And then use the following javascript to add the hidden field. I know it’s ugly at the moment and I could probably do it in a more concise way, but I’m still trying to learn the best ways. Here is all the JS code.

It appears that when I click the button, it’s might be firing twice. And I have no idea why.

var base_hamper_price;
var price_button;
var last_pressed;
var option_element;

document.addEventListener("DOMContentLoaded", () => {
    last_pressed = null;
    price_button = document.getElementById('price_button')
    base_hamper_price = price_button.dataset.price;
    let options = document.querySelectorAll('[data-price]')
    option_element = document.getElementsByName('option_id')[0];
    options.forEach((opt) => {
        opt.addEventListener('click', (e) => {
            update_option(e.currentTarget.dataset.price, e.currentTarget.dataset.optionid);
            if (last_pressed){
                    last_pressed.classList.remove("border-success")
            }
            e.currentTarget.classList.add("border-success")
            last_pressed = e.currentTarget;
        })
    })
})

function update_option(price, option_id) {
    let add_to_price = parseFloat(price.substring(2));
    let button_price = parseFloat(base_hamper_price.substring(2));
    let new_total = add_to_price + button_price;
    price_button.innerText = "A$" + new_total.toFixed(2);
    // let form = document.getElementById('form');

    option_element.value = option_id;
    // if (option_element){
    //     option_element.remove();
    // }
    // let input_elem = document.createElement("input");
    // input_elem.setAttribute("type", "hidden");
    // input_elem.setAttribute("name", "option_id");
    // input_elem.setAttribute("id", "id_option_id");
    // input_elem.setAttribute("value", option_id);
    // form.prepend(input_elem);
}

Whilst the console is showing this (which appears to be exactly the same):

<form action="/hampers/add_hamper/premium-nibbles" method="post" novalidate="" id="form">
    <input type="hidden" name="csrfmiddlewaretoken" value="XXXX">
    <input type="hidden" name="option_id" id="option_element" value="85">
    <button type="submit" class="btn btn-sm btn-success" id="price_button" data-price="A$75.00">A$89.19</button>
</form>

When I submit the form I am getting the following:

<QueryDict: {'option_id': ['undefined'], 'csrfmiddlewaretoken': ['XXXX']}>

I don’t understand why it works when hard-coded but not when injected using JS. I’ve tried to hard code the hidden field and just update the value using JS, but the value still comes back as ‘undefined’.

Advertisement

Answer

It seems that setting data-price on all the divs and my button was leading to the update option function being called twice. Once where the option_id was being set, the second time it wasn’t.

Another learning experience. Sigh.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement