How to get a form with repeating elements

The name doesn’t really say that, as I am having problems summarizing the problem. So here is a long explanation:

Let's say I add information about several contacts, and I have these fields:

  • Contact name
  • Contact method (email address, phone number, instant message)
    • If email: Show email field (say this field exists)
    • If phone number: show phone number field
    • If the instant message: Show text box

So, right off the bat, I will need JavaScript to complete this on the page itself (to add fields for adding or removing contacts), which I'm fine with. However, since I can add several contacts (and as a software developer, I don’t know how many contacts the user wants to add, it can be 1, 10 or 100)

So, my biggest problem is how I am going to structure things like names for each of the fields. Should I throw everything at things like names[] , contactmethods[] and access to things in order, or if there is a better solution.

In addition, if the server starts checking this information and finds incorrect information, I would like to be able to send the data that the client sent to the server back to the client so that they would not lose all of them that were entered. How could I do this easily?

Some background information: Technologies that are currently used (which is relevant):

  • Flask
  • JQuery
  • WTForms
+6
source share
1 answer

No need to build anything (at least on the server side) - WTForms already supports what you need - it calls them "field enclosures" , The behavior you are looking for is in wtforms.fields.FormField and wtforms.fields.FieldList

 class ContactForm(Form): name = TextField("Name", validators=[Required()]) contact_type = SelectField("Contact Type", validators=[Required()], choices=[ ("email", "Email"), ("phone", "Phone Number"), ("im", "Instant Message") ]) # `If` is a custom validator - see below email_address = TextField("Email", validators=[If("contact_type", "email", [Required(), Email()]) ]) phone_number = TextField("Phone #", validators=[If("contact_type", "phone", [Required()]) ]) im_handle = TextField("IM Handle", validators=[If("contact_type", "im", [Required()]) ]) class SignUpForm(Form): # Other fields go here contacts = FieldList(FormField(ContactForm)) 

You will also need a custom validator to check the correct field, given the user's choice:

 # CAUTION: Untested code ahead class If(object): def __init__(self, parent, run_validation=None, extra_validators=None, msg=None): self.parent = parent self.msg = msg if msg is not None else u"Invalid" if callable(run_validation): self.run_validation = run_validation else: _run_validation = lambda self, parent, form: parent.data == run_validation self.run_validation = _run_validation self.extra_validators = extra_validators if extra_validators is not None \ else [] def __call__(self, field, form): parent = getattr(form, self.parent) if self.run_validation(parent, form): return field.validate(form, extra_validators=self.extra_validators) 

When you call form.validate() on the server side, the fields will be automatically checked for compliance and errors will be filled out accordingly so that you can return them on the client side.

Creating new fields on the client side is simple, and WTForms will pick them up on the back, while you name using the same naming convention that it uses - namely field.short_name + '-' + index .

+5
source

Source: https://habr.com/ru/post/920074/


All Articles