Dynamically fill out multi-row form with htmx & jinja - jinja2

I have a large order form which contains a table (and some fields outside the table too). I would like to dynamically populate last cell of each row based on the values entered.
I'm using jinja.
Here is what my rows look like:
<tr>
<td> <input type="text" name="{{ row[0] }}_catalog_number" value="{{ row[1] }}"> </td>
<td> <input type="text" name="{{ row[0] }}_description" value="{{ row[2] }}"> </td>
<td> <input type="text" name="{{ row[0] }}_qty" value="{{ row[3] }}"> </td>
<td> <input type="text" name="{{ row[0] }}_rate"
placeholder="$"
hx-trigger="keyup changed delay:500ms"
hx-target="#{{row[0]}}-row-total"
hx-swap="innerHTML" hx-put="/{{row[0]}}/getitemtotal"> </td>
<td id="{{row[0]}}-row-total"> <input type="text" name="{{ row[0] }}_total" placeholder="$"> </td>
</tr>
The issue: no requests are getting sent...
{{ row[0] }} is an identifier unique for each row. I inspected the HTML and everything gets rendered as expected. HTMX as such works on the page, and the problem doesn't appear to be table related (removing the table and just leaving the input fields didn't help).
I suspect that hx-target="#{{row[0]}}-row-total" may be to blame because if I remove the {{row[0]}}- from the td id and from the hx-target, requests do go out (but the response will land in the first #row-total available, which may not be the right one).

Dauros found the issue - see comment above. Prepending row[0] to the id resulted in an ID starting with a number.

Related

Multiple Tags From Text Field value

I have created a form for people to subscribe to my newsletter and i would like to classify them by getting their gender and size (i'm in the garment industry). So i need to create tags.
I achieved to create the tag "newsletter", which will be the same for everyone subscribing.
Now I need to get both the size and gender on text field input and know it must be:
" (newletter, something(size), something(gender)) "
Here is the code for the contact[tags]:
{%- form "customer", class: "subscribe-form-flex" -%}<input type="hidden" name="contact[tags]" value="newsletter, ">
For the size:
<input type="hidden" class="text-field-6 desktop w-input" maxlength="256" name="size_" data-name="Size 2" placeholder="" id="Size" value="Size" >
For the Gender:
<input type="hidden" class="text-field-7 desktop w-input" maxlength="256" name="gender_" data-name="Gender 2" placeholder="" id="Gender" required="" value="Gender">
My text field IDs are then:
Size
Gender
Any idea, someone ?
Thank you in advance !
There are probably other solutions, but what I have done to solve a similar problem is
<div id="my_form_container">
{%- form "customer", class: "subscribe-form-flex" -%}
<input id="form_tags" type="hidden" name="contact[tags]"
value="newsletter">
<div id="select_container">
<select required="required" name="sizes"
onchange="var opt=this.options[0];if(opt.getAttribute('role')==='placeholder'&&!opt.selected)opt.parentNode.removeChild(opt);/*This is just to remove the placeholder*/"
id="form_sizes">
<option role="placeholder" value="">Size...</option>
<option>S</option>
<option>M</option>
<option>L</option>
<option>XL</option>
</select>
</div>
{% unless form.posted_successfully? %}
<script type="text/javascript">
$('#my_form_container form').submit(function (e) {
var $formTags = $("#form_tags");
var preferences = $("#form_sizes").val();
$formTags.val($formTags.val() + "," + preferences);
return true;
});
</script>
{% endunless %}
{%- endform -%}
</div>
So in practice you have your form with your inputs (I have added just the size) and then, before you submit the form, you modify the tag input to have all the tags you need.
I don't know your level of Javascript, let me know if you need more details.
For a Shopify store that doesn't use JQuery, you can use the below code.
Firstly create a hidden input with the name="contact[tags]" to point it at the Shopify tags field.
<input id="form_tags" type="hidden" name="contact[tags]">
Get all of your inputs and concatenate them using comma separation which will send these as separate tags.
<script>
document.querySelector("form#contact_form").addEventListener("submit", function(e){
const maleSize = document.getElementById("male-shoe-size").value;
const femaleSize = document.getElementById("female-shoe-size").value;
document.getElementById('form_tags').value = maleSize + "," + femaleSize;
});
</script>

HTML / FLASK - Dynamic Table with Checkboxes per row

With Flask / HTML, I am dynamically populating a table of directory listings where I would like the user to have the option to select single or multiple directories via a checkbox, however when I check the box on any table row besides the first, only the first row's checkbox is being selected. I have ensured that the value of the checkboxes are independent, however I would like to have each row's checkbox to be unique to one another.
HTML:
<div id="select-form">
<form action="" method="post">
<h1>{{ directory.user_entered_path }}</h1>
<table cellspacing="0" class="table">
<tbody>
<tr>
<td class="head">Filename</td>
<td class="head">Type</td>
<td class="head">Size</td>
<td class="head">Select</td>
</tr>
{% for file in dir_list %}
<tr>
<td name="name"> {{ file.file_name }}</td>
<td> {{ file.file_type }} </td>
<td> {{ file.file_size }}</td>
<td><input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="{{file}}">
<label class="form-check-label" for="inlineCheckbox1"> </label></td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
I tried the following:
To the end of your html, within the <form></form> I added a submit button for convenience, I don't know of another way to create a post request.
<form action="" method="post">
<h1>{{ directory.user_entered_path }}</h1>
<table cellspacing="0" class="table">
<tbody>
<tr>
<td class="head">Filename</td>
<td class="head">Type</td>
<td class="head">Size</td>
<td class="head">Select</td>
</tr>
{% for file in dir_list %}
<tr>
<td name="name"> {{ file.file_name }}</td>
<td> {{ file.file_type }} </td>
<td> {{ file.file_size }}</td>
<td><input class="form-check-input" type="checkbox" name="check" id="inlineCheckbox1" value="{{file}}">
<label class="form-check-label" for="inlineCheckbox1"> </label></td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- added this button -->
<button type="submit" name="submit-button" value="Submit">submit</button>
</form>
Then I added this route to a flask app.py
from flask import request, render_template
#app.route('/stack-dynamic-checkboxes', methods=["POST", "GET"])
def dynamic_checkboxes():
if request.method == 'POST':
if request.form['submit-button'] == "Submit":
for checkbox in request.form.getlist('check'):
print(checkbox)
def afile(x):
return {'file_name':f'file {x}',
'file_type':f'type {x}',
'file_size':f'size {x}'}
dir_list = [afile(x) for x in range(10)]
directory = {'user_entered_path':'a path'}
return render_template( 'testing/stack-dynamic-checkboxes.html',
directory=directory,
dir_list=dir_list )
When I run the app and navigate to the page with your html, select some checkboxes and press submit, I get information about the files printed to my console. They are all dictionaries in this format
{'file_name': 'file 0', 'file_type': 'type 0', 'file_size': 'size 0'}
I hope this was wat you were looking for.
I've been searching for a way to do this for a while. I'm glad you posted this question because I didn't understand the way I had to set up the HTML part correctly, so, thank you!
In the future, It would be nice to have a little bit more context, what your code looks like perhaps, as I'm uncertain whether this is what you were looking for

Why list elements after space disappear when passed from views to Django template?

I use Django 2.1. I have some code in views.py:
views.py
...
zipped = zip(ph, mean)
return render(request,'project/list.html',
{'section': 'project', 'lines': zipped})
so far everything is correct, I debugged and all works.
Data
ph = ['Pre formation', 'Nice view'] #as an example not exact values
mean = [10.0, 14.6]
However inside html
html
{% for ph, mean in lines %}
...
<td><input type="text" size="35" name="txt1" value={{ph}}></td>
<td><input type="text" size="35" name="txt2" value={{mean}}></td>
...
{% endfor %}
Data I get
Pre 10.0
Nice 14.6
Question:
Why does it take only the text till space inside html? Inside views I debugged zipped has all information.
How can I fix it?
Try:
{% for ph, mean in lines %}
...
<td><input type="text" size="35" name="txt1" value="{{ph}}"></td>
<td><input type="text" size="35" name="txt2" value="{{mean}}"></td>
...
{% endfor %}
Quotes around value are missing.

Need to bind data

Following is my code, I need to bind data to ng-model, when I bind ng-model = "value", I can see the value in the text field, but I want to update the value on changing the text input.
<tbody ng-repeat="action in model.editAction">
<tr ng-repeat="(key, value) in action | orderBy: '-key'">
<th> {{ key }} </th>
<td>
<input type="text" class="form-control"
ng-model="model.editAction.value" name = "key"
required/>
<span style="color:red" ng-show="main.AssetURL.$error.required ">Service name</span>
</td>
<td> {{ action.DESCRIPTION }} </td>
</tr>
</tbody>
In your controller define a $scope var like this:
$scope.value
In your input, place just value inside ng-model:
ng-model="value"
This way you are binding values between your view and your controller.
You can use ng-change for getting the new values which you input
<input type="text" class="form-control"
ng-model="model.editAction.value" name = "key" ng-change="onChangeValue(model.editAction.value)"
required/>
And in your controller,
$scope.onChangeValue=function(value){
console.log(value);
//you should see the new updated value
}

html submit data which not in Text Fields

I need display a table contain text field and button like:
<table border="1">
<tr>
<td>name</td>
<td>id</td>
<td>icon</td>
<td> </td>
</tr>
{% for i in gs %}
<tr>
<td align='center'>{{ i.id }}</td>
<td align='center'>{{ i.name }}</td>
<td align='center'><input type="text" name="icon" value="{{ i.icon }}" /></td>
<td align='center'><input type=submit value="update" style="width:100%"></td>
</tr>
{% endfor %}
If user want to modify 'icon', then input new value in the text field and click update. But the problem is in django function, I only gets 'icon' value in 'request.POST', I don't know which id is updating. So how to pass 'i.id' into POST with icon together?
You can add hidden input field in the form to get id. In your template add another input field
<td align='center'><input type="text" name="icon" value="{{ i.icon }}" /></td>
<td align='center'><input type="hidden" name="icon_id" value="{{ i.id }}" /></td>
Then your view you will have icon_id field in submitted data.