WEB: Submitting files + text fields, use single form or separate? - forms

I'm currently working on a simple frontend that will allow users to input data into text fields and also upload files on the same form.
I know that I'll have to use multipart/form-data in order to send the files, but I'm curious as to what would be the best way to also send the text data. My options are:
Submit files and text data in a single form using multipart/form-data
Separate files and text data between two different endpoints, allowing me to format the text data to JSON client-side before sending it off
I don't think doing either would be terribly difficult, but I'm curious as to what is generally considered to be the best practice in this scenario.

This depends on the workflow you expect of your users.
If the fields you want them to fill in are tightly bound to the file you upload, do them all in one form. For example, if it's an image being uploaded and the field contains the image's caption, they go together and should be in a single form.
If it makes sense from your page to just upload the file, or just fill out the fields in the form and submit them, use two form objects.
You probably won't know how well this works until you do some usability testing. You may have to change it up to get everything working smoothly.

Related

Dancer and generating forms

I have an issue where forms are validated and if do not pass validation (validation is done in the back-end) are re displayed with original submitted data for the user to change. Originally this was not huge as I could just pass param data back into the template and have it re-displayed to the user. However, I came across issues with getting drop-downs and check boxes to retain the submitters original choices.
I checked out some of the Dancer friendly modules that did form validation and they seem nice, however, I have one more constraint: The forms and data selected needs to be able to be rebuilt and displayed again at a later time. So that means the data will need to be retrieved and the form built again displaying the same information previously selected, dropdowns already preselected, checkboxes checked, and data with the inputs.
I do not mind generating the forms and their selections dynamically from the backend using CGI form generating methods, but how can I get that data to play nice with dancer and display inside of a template?
If you're going to redisplay at a later time, it seems to me that you could go with a poor man's solution--save the rendered form with stuff selected to disk or database, and when it needs to be displayed again, just thow that cached stuff at them--or write the params to storage, and when you need to redisplay, go through the same code that generates the form now but use the saved params.
The "poor man's method" would be easy to implement but would bite you later when you find you are showing people stale versions of the form or whatever. (This is also a possible issue with the other version--the set of parameters might change over time, so there's risk there, too, but I would think less risk as you are caching less.)
I'm sorry that this is a "how to solve your problem" answer rather than a "here's a module that solves your problem answer". However, it's not too hard to store a set of params as a json blob or some other sort of frozen object, and there are modules for all the pieces of this.

Multiple form components within a single form in CQ5.6/5.5

I need to create a form on my page which would accept values from the end user, validate the input (basic stuff, nothing fancy, to check whether required fields are filled etc.) along with a captcha to eliminate spam bots.
Currently, I have a standalone reCaptcha component set up for my form. It works fine on it's own. I was thinking along the lines of adding this along with any of the out of the box form components that CQ5 provides (the address component caught my fancy).
The problem arises with the validation. When I click submit, the validations for the address component never seem to execute. Which leads me to my question.
i) Is it allowed for me to continue with my current methodology (i.e 1 main form component which contains one reCaptcha component and one address component)? If I can, how can I map the validations accurately for the entire form to behave as I want when I hit submit. (I would need the address form to check for required fields, the reCaptcha to check if the challenge field is valid, in that order)
ii) If I cannot carry out the task in this way, would I have to create an entirely new component for my form, one which includes the code for both the address component and the reCaptcha component and include both their validations within 1 file? Logically, I can see the merit of this approach, it does seem much easier. But I would like to maintain the reCaptcha component as a stand alone, to effect reusability across my site.
A similar topic does exist on how to handle Multiple forms on a single page, but since it involves Ruby, which I have next to zero knowledge on, I couldn't really implement.
I'd appreciate it if I could get some information on how to achieve this in context to CQ5.
Thanks
(apologies for the really long wall of text)
after tinkering about with my form for a while, I was eventually able to get it to work!
So, yes it is indeed possible to have a multiple form components within a single form. The issue with validations can be sorted out by taking a look at how the validations are managed for any of the OOTB form field components individually.
To clarify, the OOTB Captcha component uses the Layout.printError() method to display any issues with validation. I sorta reworked this into my Recaptcha component, and made the necessary changes into the servervalidation.jsp. Worked fine!
And with respect to the 2nd point in the question, I'd suggest not going down that road as I feel it's always better if my component is stand alone.

Yesod forms with page flow

Certain forms are too complicated to have them fit on one page. If, for example, a form involves large amounts of structured data, such as picking locations on a map, scheduling events in a calendar widget, or having certain parts of a form change depending on earlier input, it is of value to be able to break up a certain form over multiple pages.
This is easy to do with dynamic web pages and Javascript, as one would simply create a tab widget with different pages, and the actual submitted form would contain the whole tab widget and all of its input fields, yielding a single POST request for the entire operation.
Sometimes, however, it takes a long time to generate certain input fields; they might even be computationally intensive even after the page has been generated, taxing the low-end computer user's browser. Additionally, it becomes difficult or impossible to create forms that adapt themselves based on earlier input.
It therefore becomes necessary to split up a certain form over multiple full page requests.
This can prove to be difficult, especially since the first page of a form will POST to /location/a, which will issue a redirect to /location/b and requested as GET by the client. Passing the stored form data from POST /location/a to GET /location/b is where the difficulty lies.
Erwin Vervaet, the creator of Spring Web Flow (A subproject of the Spring framework, mostly known for its dependency injection capabilities) once wrote a blog article demonstrating this functionality in said framework, and also comparing it to the Lift Web Framework which implemented similar functionality. He then presents a challenge to other web frameworks, which is further described in a later article.
How would Yesod face this problem, especially considering its stateless REST-based nature?
Firstly, there's no pre-built solution to this in existence yet (that I'm aware of at least). And I'm not familiar with how the other frameworks mentioned solve the problem. So what I say here is pretty much conjecture. I'm fairly certain it would work, however.
The crux of the issue here is encoding page A's POST parameters into the GET request for page B. The simplest way to do that would be to stick page A's POST parameters into a session variable. However, doing so would break navigation pretty thoroughly: back/forward wouldn't work at all as described.
So we come back to REST: we need to encode the POST parameters into the request itself. That really means putting the information in either the requested path, or the query string. And the query string probably makes the most sense.
I'd be concerned about putting the raw POST parameters into the query string, as that would allow any proxy server to easily snoop the contents. So I'd like to leverage the existing cryptography from clientsession. In other words, we'll stick a signed, encrypted version of the previous form submission in a query string parameter.
To make it a bit more concrete:
User goes to page A via GET.
User submits page A via POST.
Server validates form submission, gets a value, serializes it, encrypts/hashes it.
User is redirected to page B as a GET, with a query string parameter containing the encrypted/hashed value from page A.
Continue this process as many times as desired.
On the final page, you can decrypt the query string parameter and have all of the form submissions.
This looks like it would be a fun add-on package to write if anyone's interested.

How do you handle multiple files in a form submission using Apache2::Upload?

I'm writing a small web application using Perl, HTML::Mason and Apache.
I've been using Mason's usual <%args> method for receiving 'normal' form parameters, and Apache2::Upload for receiving files.
However, I want to write a page that allows a user to upload multiple files, and I'd like to take advantage of HTML5's multiple attribute to input fields. This will look to the server as though there were multiple file inputs in the form with the same name.
The interface for Apache2::Upload doesn't seem to directly support this, allowing you instead to just get the data for a file with a particular parameter name. The documentation alludes to using APR::Request::Param::Table, but I can't find any documentation for doing that.
Please note that I'm not interested in answers that involve adding extra file input fields with different names. This is trivial to handle on the server, and my question doesn't involve front-end scripting at all.
Use the multiple attribute (in the form as you described) and then, after submission, call the Apache request object's upload method. That will give you a list of Apache2::Upload instances.
Good luck!

What to do with CSV after export on the iPhone?

One of the requested features for my apps is to have an export feature. Most of the time the data is table-like in nature. As an example, users might enter every day what types of food they ate that day, and how many portions of each food type. As the data is table-like, I figure the most useful for export would be into CSV format. Then it can be read in spreadsheet software.
I'm confident I can get the data into a CSV like format without too much trouble, and found this post would should help me: How to convert data to CSV or HTML format on iOS?
What I'm wondering about is what I can do with the file once it has been created? Can I attach it to an email? How else can I make it available to the user so that it has some use?
Alternatively, am I going about this the wrong way and would there be a better way to offer an export function?
I would suggest using MFMailComposeViewController and attaching your CSV file to it. This has the benefit of allowing the user to forward to the file to multiple recipients, customize the email body etc. You can also insert HTML into the email body, so if the data isn't too large you could simply present a table of the information within the email itself.
To send an attachment follow the instructions here.
Usually when an iPhone app needs exporting functionality you have the following options:
Attaching it to an email (as you mentioned)
Sending it to a server (with HTTP or any other TCP/IP based protocol)
Exposing it with a small WebServer you code inside your app (like the Video Camera APPs for 3G and older iPhones do)
Unfortunately, you can't use iTunes for sync your exported file. At least you can't with the current version of the SDK.
Instead of CSV, I would use XML. It can also be read with Excel (or any other spreadsheet), plus you won't have to deal with COMMA (or any other separator for that matter) escaping.