Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamically add field to a form

I have 3 fields in my form. I have a submit button and a button to "Add additional Field". I understand I can add fields using __init__ method in the form class.

I am new to Python and Django and am stuck with a beginner question; my question is:

When I click the "Add additional field" button, what is the process to add the additional field?

Does the form have to be rendered again?

How and when do I call __init__ or do I even have to call it?

How do I pass arguments to __init__?

like image 732
Afshin Avatar asked May 26 '11 16:05

Afshin


People also ask

How do you create a dynamic form?

To create a form dynamically with JavaScript, we can use the document. createElement method to create the element. Then we can use the setAttribute method to set the element attributes. Then we can use the appendChild method to append the elements into the parent element.

What are dynamic fields in forms?

Dynamic Fields Add-on for Google Forms™ populates values of selection fields. Questions of type Multiple-choice, Drop-down, Checkbox or Grid can be updated by data from Sheets, Contacts or Groups. Create in Google Forms™ dynamic choice boxes.

How do you add a field in HTML?

The <input type="text"> defines a single-line input field for text input.


Video Answer


2 Answers

Your form would have to be constructed based on some variables passed to it from your POST (or blindly check for attributes). The form itself is constructed every time the view is reloaded, errors or not, so the HTML needs to contain information about how many fields there are to construct the correct amount of fields for validation.

I'd look at this problem the way FormSets work: there is a hidden field that contains the number of forms active, and each form name is prepended with the form index.

In fact, you could make a one field FormSet

https://docs.djangoproject.com/en/dev/topics/forms/formsets/#formsets

If you don't want to use a FormSet you can always create this behavior yourself.

Here's one made from scratch - it should give you some ideas. It also answers your questions about passing arguments to __init__ - you just pass arguments to an objects constructor: MyForm('arg1', 'arg2', kwarg1='keyword arg')

Forms

class MyForm(forms.Form):     original_field = forms.CharField()     extra_field_count = forms.CharField(widget=forms.HiddenInput())      def __init__(self, *args, **kwargs):         extra_fields = kwargs.pop('extra', 0)          super(MyForm, self).__init__(*args, **kwargs)         self.fields['extra_field_count'].initial = extra_fields          for index in range(int(extra_fields)):             # generate extra fields in the number specified via extra_fields             self.fields['extra_field_{index}'.format(index=index)] = \                 forms.CharField() 

View

def myview(request):     if request.method == 'POST':         form = MyForm(request.POST, extra=request.POST.get('extra_field_count'))         if form.is_valid():             print "valid!"     else:         form = MyForm()     return render(request, "template", { 'form': form }) 

HTML

<form>     <div id="forms">         {{ form.as_p }}     </div>     <button id="add-another">add another</button>     <input type="submit" /> </form> 

JS

<script> let form_count = Number($("[name=extra_field_count]").val()); // get extra form count so we know what index to use for the next item.  $("#add-another").click(function() {     form_count ++;      let element = $('<input type="text"/>');     element.attr('name', 'extra_field_' + form_count);     $("#forms").append(element);     // build element and append it to our forms container      $("[name=extra_field_count]").val(form_count);     // increment form count so our view knows to populate      // that many fields for validation }) </script> 
like image 106
Yuji 'Tomita' Tomita Avatar answered Sep 21 '22 12:09

Yuji 'Tomita' Tomita


I've had a case when I had to dynamically create forms with dynamic fields. That I did with this trick:

from django import forms  ...  dyn_form = type('DynForm',  # form name is irrelevant                 (forms.BaseForm,),                 {'base_fields': fields}) 

Refer to this link for more info: Dynamic Forms

But in addition to that I had to inject fields as well i.e. dynamically add fields to a form class once it was created.

dyn_form.base_fields['field1'] = forms.IntegerField(widget=forms.HiddenInput(), initial=field1_val) dyn_form.base_fields['field2'] = forms.CharField(widget=forms.HiddenInput(), initial=field2_val) 

And that worked.

like image 28
Al Conrad Avatar answered Sep 20 '22 12:09

Al Conrad