There are several writeups on how to use javascript to add forms dynamically to a Django formset. For example this or this.
I just learned about htmx.
How can I add forms dynamically to a Django formset using htmx instead of hand-coded javascript? I thought maybe I could use click-to-load, but it seems odd to call back to the server to get an empty row. Maybe this just isn't an htmx thing.
With HTMX, instead of the complication of formsets, you can dynamically add forms, and swap in the resulting model instance on submit.
This example todo app provides a demonstration of the approach. It allows you to add additional items by appending a form, and upon submitting successfully, swaps in the model instance resulting from that form submission. The end result is much like using formsets.
I just answered a similar question here: The right way to dynamically add Django formset instances and POST usign HTMX?
Here's the summary of my approach:
Create a view function to bring in your new formset via an hx-get.
In that view function, build the html of your new formset by starting with
YourFormset.empty_form to get the basic html, and then replace the default "__prefix__" with the number representing the index the new formset should have in its id, name and label attributes. For example, if it's the second formset on the page its id will be id_form-1-title (changed from id_form-__prefix__-title).
In the html for the new formset, also include a hidden input element to replace the one creted by django's ManagementForm to update the value of form-TOTAL_FORMS. Place hx-swap-oob="true" on that input so that it replaces the old element.
A longer explanation with example code is at: The right way to dynamically add Django formset instances and POST usign HTMX?
Docs reference: https://docs.djangoproject.com/en/4.1/topics/forms/formsets/
Related
I've been experimenting with Symfony forms for some time. Without a doubt Symfony's FormType is a great feature which help create robust forms, especially with related entities (eg. ManyToMany, OneToMany etc.). The FormType makes my job a lot less complicated and easy when it comes to persistence. One of these case is the embedded forms, where u have multiple(lets say Category and Tag) entities with ManyToMany relation. Using FormType, I can create a 'Select dropdown' field using ChoiceType form field to choose category from, embed another CollectionType field with multiple 'text input' fields to accept multiple tagname, and finally a submit button. All I need is to add the cascade = {persist} option using annotations on the categoryname property of the Category entity and Wallah!
Now what if I wanted to create a single input field which can accept multiple tags, instead of having multiple input fields. Like this:
To do this I can create an <input> element using CollectionType form field, and then in my html.twig I can insert the javascript(jquery/AngularJS) dependency as attributes.
This can be done by using jquery Chosen or Select2 https://www.sitepoint.com/jquery-select-box-components-chosen-vs-select2/
or by using AngularJS ngTagsInput component http://mbenford.github.io/ngTagsInput/
Not just this particular case, I know that jquery delivers almost everything u want to do on the client side, and works good with Symfony, but I've been looking into AngularJS for some time now and it is undoubtedly true that it is further a step ahead of jquery or any other javascript framework. Thus my opinion is a little biased towards AngularJS.
The thing is, jquery(Chosen/Select2) uses <select> element and the AngularJS(ngTagsInput) uses custom <tags-input> element to display this field. Although with AngularJS I can make some elementary changes and convert the <tags-input> element to <div ngTagsInput> but I can't convert it to <input ngTagsInput> because the standard HTML<input> element has no closing tag, thus many features like auto-complete don't work. Customizing ngTagsInput & autoComplete directives (AngularJS)
Problem: For Symfony to persist the CollectionType field input in the standard way I need to use the <input> element to display the field.
Questions:
How do I make this work?
How compatible are Symfony and AngularJS? And is it recommended to use them together?
All help is appreciated.
Thanks in advance!
I've built a dynamic set of form inputs using vue.js, where the form inputs are generated from an external list of inputs.
My problem is that I don't see how I can bind the input values back to the vue model, so that the vue instance can access / interact with the form values.
I've created a basic fiddle to give you the idea here: https://jsfiddle.net/gzprj5ef/
Is it possible to update the vue instance with the form values?
You have to remove double brackets when you are using v-model.
Here is the updated jsfiddle
You can use v-model="input.value", and you can take a result in variable 'inputs'.
I have a situation where i have to modify a form (to dynamically add a table) via jquery after it's been rendered / created.
The problem is that when the form is submitted, and redisplayed because of errors or validation issues, I don't know of a good way to save and redisplay the data they've entered into the fields I've created dynamically.
Any suggestions would be appreciated.
You probably want to use something like jQuery Populate.
Dynamically added data don't differ from the static added ones. You have to use 'validate()' method to prevent submitting and rendering the html-code with errors, in this case user will see the dynamically added data.
I am developing a web application. I have a page with a form, form1, and I am pushing another page which also has a form, form2, inside form1. Both the forms have some values. I want to serialize both the forms. When I specify the root form (form1) like $('#form1').serialize(); it serializes the root form (form1) only, not form2.
If specify like this $('#form1, #form2').serialize(); and $('form').serialize(); it sealizes all the forms.
What is wrong with this jQuery $('form1').serialize(); which serializes root form only, not form2?
I tried with a jsFiddle example, in which it works fine. What could be the issue in my web application form?
Nested forms are not allowed in HTML. jQuery isn't designed to handle them. Don't create them.
Even it is not supported for your purpose you can use :input selector.
$('#form1 :input').serialize();
for the performance using filter highly recomended.
$('#form1 > *').filter(':input').serialize();
If you can explain why you are using nested forms maybe we can suggest some workaround. for example if you only use the second form for AJAX request you can cover it by a div to easily select or give those form items an extra class and use the similar selector for them.
I am researching ways on how to dynamically add form fields for nested models and stumbled accross the nested_form plugin by ryanb. No doubt this is a a great piece of code, but I wondered why does it have to be so sophisticated?
Example: A form for creating / adding a project has one or more tasks assigned. The user can dynamically add more tasks by clicking on a add-task button. A project must have at least one task. Each task has a name and a description.
So why not just:
- When generating the html, sourround each set of task fields with a div given an ID such as "dynamic_fields"
- When the user clicks the add-task button, call a JavaScript function via link_to_function to clone the dynamic_fields subtree. Insert the new set of fields at the bottom of the task list.
- Via JavaScript, remove the values of the newly added fields and replace the child ID with something unique (Ryan suggests using a value based on the current time)
I am aware that the nested_forms plugin also works for deeper nesting structures, but given my simple use case with only one level of hierarchy, is the approach outlined above practical? Or am I missing something important? Any guidance on this topic is appreciated.
Basically, the plugin works as you describe but a form partial is used as the basis.
The ids of nested objects must be unique and it's really easy to stick to the current millisecond time to do that.
Your way to handle the problem would work but would require some additional html to catch the required parts of the form and match what belongs to which additionnal object.
Ryan Bate's code seems complicated but it's not. It introduces complex methods only to make your view look good.
I think there is another solution to this question, a gem named cocoon.