`hx-vals` fails to parse `this.value` for POST request on select object
Closed this issue · 4 comments
HTMX | Django |
---|---|
v: 2.0.2 | 5.0 |
Im delivering the question
and question_type_options
without trouble. The problem lies when hx-vals='{"question_type": this.value}'
:
<select class="form-select question-type"
hx-post="{% url 'app:update_question_type' pk=question.pk %}"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-trigger="change"
hx-vals='{"question_type": this.value}'
onchange="console.log('Selected value:', this.value)"
>
{% for option_type in question_type_options %}
<option value="{{ option_type.field }}" {% if option_type == question.question_type %}selected{% endif %}>
{{ option_type.description }}
</option>
{% endfor %}
</select>
The output in the console shows:
Selected value: cbx // a valid string option
htmx.org@2.0.2:1 SyntaxError: Unexpected token 'h', ..."n_type": this.value}" is not valid JSON
at JSON.parse (<anonymous>)
at S (htmx.org@2.0.2:1:5838)
at wn (htmx.org@2.0.2:1:35728)
at En (htmx.org@2.0.2:1:36001)
at Cn (htmx.org@2.0.2:1:36056)
at he (htmx.org@2.0.2:1:41110)
at htmx.org@2.0.2:1:22304
at HTMLSelectElement.i (htmx.org@2.0.2:1:21340)
Then on the server-side:
the view function which controls "app:update_question_type" is this:
def update_question_type(request: HttpRequest, pk: int) -> HttpResponse:
# Log raw request body to debug
print(f"Request POST data: {request.body}")
new_type = request.POST.get('question_type', '')
print(f"Parsed new_type: {new_type}")
if not new_type or new_type == "undefined":
print("Invalid question type received.")
return JsonResponse({'success': False, 'error': 'Invalid question type provided.'}, status=400)
try:
question = Question.objects.get(pk=pk)
q_type = QuestionType.objects.get(field=new_type)
question.question_type = q_type
question.save()
return JsonResponse({'success': True, 'new_type': new_type})
except QuestionType.DoesNotExist:
print(f"QuestionType does not exist for field: {new_type}")
return JsonResponse({'success': False, 'error': 'Question type does not exist.'}, status=400)
except Exception as e:
print(f"Exception occurred: {str(e)}")
return JsonResponse({'success': False, 'error': str(e)}, status=500)
The terminal output shows:
Request POST data: b''
Parsed new_type:
Invalid question type received.
Bad Request: /mobile/update-question-type/14
[28/Aug/2024 08:59:59] "POST /app/update-question-type/14 HTTP/1.1" 400 62
Everything works fine if i just replace this.value
with a valid string like in hx-vals='{"question_type": "lst"}'}
.
Alse, replacing by hx-vals='js:{question_type: this.value}'
raises a different error:
htmx.org@2.0.2:1 Uncaught
TypeError: Cannot read properties of undefined (reading 'forEach')
at Ln (htmx.org@2.0.2:1:37346)
at he (htmx.org@2.0.2:1:41107)
at htmx.org@2.0.2:1:22304
at HTMLSelectElement.i (htmx.org@2.0.2:1:21340)
Ln @ htmx.org@2.0.2:1
he @ htmx.org@2.0.2:1
(anonymous) @ htmx.org@2.0.2:1
i @ htmx.org@2.0.2:1
found a solution using name=
:
hx-post="{% url 'app:update_question_type' pk=question.pk %}"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-trigger="change"
name="question_type"
Also, looked up in the code, and saw that the hx-vals
element only runs JS if used the js:
tag, but is strange the error outputed in the comment above. Would be nice if added to the documentation some examples using POST requests :)
in your first example it reported that the format you specified was not valid json because you had not used the js: or javascript: prefixes to activate hx-vals javascript evaluate feature.
In the second example the value of this.value evaluated to undefined which will throw this error. When it runs the evaluate it runs the eval in global scope where this = window and window does not have a value. To test how it might work just enter the browser dev tools and go to the console of the running application and anything you type into the console here will also be in that same global window state so you can test what works manually this way. often you write a global function to get the data you want to return and then call that function in your hx-vals.
in your first example it reported that the format you specified was not valid json because you had not used the js: or javascript: prefixes to activate hx-vals javascript evaluate feature.
In the second example the value of this.value evaluated to undefined which will throw this error. When it runs the evaluate it runs the eval in global scope where this = window and window does not have a value. To test how it might work just enter the browser dev tools and go to the console of the running application and anything you type into the console here will also be in that same global window state so you can test what works manually this way. often you write a global function to get the data you want to return and then call that function in your hx-vals.
Hmmmmm that's very elucidative actually! Thank you!