inserting response as value of input field with htmx in flask

798 views Asked by At

I have an html form with an input field. As the user is typing, the value of the input field gets sent to a flask route (with htmx), processed there, returned to the form and should replace the current value (with htmx) of the input field with the processed data, received from the route.

All this should happen on the fly, as the user is typing. Automatically adding special characters or spaces between certain characters, like the input fields for entering creditcard numbers. (They put spaces between the 4th and the 5th character automatically.)

Sending the value from the input to the flask route is accomplished with htmx. I can see that this part is working, because I print out the received data in the flask route to the console and it is correct. To ensure receiving the value, from the route as a response, in the form is working, I have set the hx-swap in the form tag to "afterend". With that the response gets added to the html after the input field, as expected. (Everything is happening on the fly, as I am typing)

But the received value should replace the existing value inside the input field and I can't figure out how to accomplish this.

The python file with the flask route

@landingpage_bp.route("/process", methods=['PUT'])
def process_data():
    data = request.form['access-key']
    print("access-key:", data) #seeing in the console that the received data is correct
    processed_data = f"{data}000" #example processing
    print("processed_data:", processed_data) #seeing that the data is processed correct

    return jsonify({'value': processed_data})

The portion of the html file with the form and the htmx

<form hx-target="#access-key" hx-swap="afterend" autocomplete="off">
    <input type="tel"
         id="access-key"
         name="access-key"
         placeholder="###.###.###.###"
         pattern="[0-9]{3}.[0-9]{3}.[0-9]{3}.[0-9]{3}"
         maxlength="15"
         hx-put="/process"
         hx-trigger="keyup changed delay:500ms"
         value=""
         required
    >
</form>
1

There are 1 answers

1
suchislife On BEST ANSWER

To replace the input field's value dynamically, you can use JavaScript in the Flask response to directly update the input field's value attribute. The htmx hx-swap attribute and hx-target attribute can help you update the specific element you want.

HTML Example:

<form hx-target="#access-key" hx-swap="outerHTML" autocomplete="off">
    <input type="tel"
         id="access-key"
         name="access-key"
         placeholder="###.###.###.###"
         pattern="[0-9]{3}.[0-9]{3}.[0-9]{3}.[0-9]{3}"
         maxlength="15"
         hx-put="/process"
         hx-trigger="keyup changed delay:500ms"
         hx-swap="outerHTML"
         value=""
         required
    >
</form>

Python Flask Route Example:

from flask import Flask, jsonify, request, render_template_string

@landingpage_bp.route("/process", methods=['PUT'])
def process_data():
    data = request.form['access-key']
    processed_data = f"{data}000"
    return render_template_string('<input type="tel" id="access-key" value="{{ value }}" hx-put="/process" hx-trigger="keyup changed delay:500ms" hx-swap="outerHTML" />', value=processed_data)

By setting hx-swap to "outerHTML", you are replacing the entire element with the new one received from the server, thus updating its value.

I'm really liking htmx.

Update based on comment

You can use hx-boost attribute on the form to allow htmx to handle the form submission via AJAX, and hx-target to specify the target input. Then respond with a JavaScript snippet from Flask that sets the input value.

HTMX within HTML:

<form hx-boost="true" hx-target="#access-key" hx-swap="none" autocomplete="off">
    <input type="tel"
         id="access-key"
         name="access-key"
         placeholder="###.###.###.###"
         pattern="[0-9]{3}.[0-9]{3}.[0-9]{3}.[0-9]{3}"
         maxlength="15"
         hx-put="/process"
         hx-trigger="keyup changed delay:500ms"
         required
    >
</form>

Flask Route:

@landingpage_bp.route("/process", methods=['PUT'])
def process_data():
    data = request.form['access-key']
    processed_data = f"{data}000"
    response = jsonify({"value": processed_data})
    response.headers["HX-Trigger-After-Swap"] = "updateInputValue"
    return response

JavaScript in HTML to handle the custom event (place this in the HTML head or before the closing body tag):

<script>
document.body.addEventListener('updateInputValue', (event) => {
    const detail = event.detail;
    const input = document.getElementById('access-key');
    if (input) {
        input.value = detail.value;
    }
});
</script>

This method sends a JSON response with the processed data and triggers a custom event after htmx swaps the content. The JavaScript listener then updates the input value without replacing the entire input element.