I’m trying to add/remove forms from formsets dynamically on button press. I am looking at an older example for JS to perform this action but I have multiple formsets but when I delete all of the forms for one of the formsets, obviously the addForm command no longer works as there are no forms to clone.
That being said, I think a functional method would be to start with a hidden form and then copy the hidden form and display that form on demand. I just don’t know how exactly to do that.
Ideally, I’d like to not show any forms until the button press but not certain about how to do it. My current setup is shown below.
HTML:
<div class="selection">
<div class="forms">
<!-- {% for dict in formset.errors %}
{% for error in dict.values %}
{{ error }}
{% endfor %}
{% endfor %} -->
<form id="general-formset" method="POST">
{% csrf_token %}
{{ generalFormset.management_form }}
{% for form in generalFormset %}
<div class="formset">
{{ form.as_table }}
<button id="remove-form" type="button" onclick="removeForm(this)" display="None">Remove Constraint</button>
</div>
{% endfor %}
<button id="add-form" type="button" onclick="addForm(this)">Add Constraint</button>
</form>
<form id="specific-formset" method="POST">
{% csrf_token %}
{{ specificFormset.management_form }}
{% for form in specificFormset %}
<div class="formset">
{{ form.as_table }}
<button id="remove-form" type="button" onclick="removeForm(this)">Remove Constraint</button>
</div>
{% endfor %}
<button id="add-form" type="button" onclick="addForm(this)" display="None">Add Constraint</button>
</form>
<button id="submit" type="button">Submit</button>
</div>
</div>
JavaScript:
<script>
let submitButton = document.querySelector("#submit")
submitButton.addEventListener('click', submitForms)
function submitForms(e){
document.getElementById("specific-formset").submit();
document.getElementById("general-formset").submit();
}
function addForm(e){
let container = e.parentElement
let form = container.querySelectorAll(".formset")[0].cloneNode(true)
let formNum = container.querySelectorAll(".formset").length-1
let formRegex = RegExp(`form-(\d){1}-`,'g')
let totalForms = container.querySelector("#id_form-TOTAL_FORMS")
formNum++
form.innerHTML = form.innerHTML.replace(formRegex, `form-${formNum}-`)
container.insertBefore(form, e)
totalForms.setAttribute('value', `${formNum+1}`)
}
function removeForm(e){
let parent = e.parentElement
let container = parent.parentElement
let formNum = container.querySelectorAll(".formset").length-1
let totalForms = container.querySelector("#id_form-TOTAL_FORMS")
parent.remove()
formNum--
totalForms.setAttribute('value', `${formNum-1}`)
}
</script>