Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Organizing Form Input

by Spidy (Chaplain)
on Feb 23, 2007 at 15:43 UTC ( #601746=perlquestion: print w/ replies, xml ) Need Help??
Spidy has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, Fellow Monks.

For a recent project, users are encouraged to fill in a form with a varying number of fields - all of the fields have the same basic premise(being an answer to a question), but need to have some sort of way for me to retrieve all of them using CGI.pm. Users are able to dynamically add fields(which would also mean dynamically naming them), up to a possible limit of infinity or so. I know that I could name the fields 'answer<foo>', where <foo> is a number from 1..infinity and then just retrieve all of them, but I'm wondering: is there a better way that I can organize and retrieve these values? In my mind I'm thinking of an array of some sorts, but I'm not sure if that's actually possible.



Thanks,
Spidy


Edited Addendum: I am absolutely not going to use Javascript or Ajax to do this, as this feature is being developed for users that do not have Javascript disabled. Also, a PHP version of what I'm talking about can be seen here, if you look under "Creating a PHP array in an HTML form".

Comment on Organizing Form Input
Re: Organizing Form Input
by Herkum (Parson) on Feb 23, 2007 at 16:11 UTC

    It seems to me that you are implying that you are using Javascript to fields to the form, have you considered using Javascript to add the answers to a 'Answer' variable that is associated with a specific question.

    Another way of dealing with it is to use AJAX, which is probably a more complicated implementation, but I believe, is more flexible in the way data is sent to the server.

      While I am planning on using some Javascript to accomplish this, I am also generating the form entries using HTML for users who have javascript disabled. I am seeking a solution that will work for both.
Re: Organizing Form Input
by suaveant (Parson) on Feb 23, 2007 at 16:27 UTC
    You can also do things like encode data into the name like field_1_info_here or maybe even better would be to put data about the field in a hidden field

    As Herkum suggests, though, AJAX would by far be the most flexible.. I send complex data structures back and forth to Perl from JS using JSON in AJAX.

    More of an example may help us help you more.

                    - Ant
                    - Some of my best work - (1 2 3)

Re: Organizing Form Input
by andyford (Curate) on Feb 23, 2007 at 16:30 UTC

    Here's a concept that might work.
    Use javascript to add fields and hold the answers in a javascript array. You can dynamically add and make the input fields visible with javascript and CSS.
    Then for submission, just concatenate the js array into a big string variable, submit the array as one CGI parameter, and let the CGI code take it back apart into an array.
    Not sure how big one parameter can be though. Maybe not infinite :) You really should set some limit anyway for one submission.

    non-Perl: Andy Ford

      For something like that, you'd pretty much have to submit it as a POST, but I assume the OP is already using POST rather than GET. You can then set $CGI::POST_MAX to make the size limit more-or-less whatever you want. AFAIK, CGI only limits the total size of the POSTed request and you can split that up however you want across as many or few parameters as you like.
Re: Organizing Form Input
by blue_cowdawg (Monsignor) on Feb 23, 2007 at 16:59 UTC

    Yon Monk,
    Your question has me a bit confused.

        Users are able to dynamically add fields(which would also mean dynamically naming them), up to a possible limit of infinity or so.

    Exactly what does that mean? IMHO allowing the end user to drive an application to that level is a Bad Idea™.

    If I am reading between the lines correctly you are writing an application that is a quiz of some sort. Am I close?

    Here's my approach for that type of an application:

    First I'd create a table in a database (fill in your favorite database here) that had the questions. Such as:

    create table quiz_questions ( quiz_question_id serial not null primary key, question TEXT );
    Depending on if I'm asking multiple choice questions or ask straight questions witn only once answer (much harder to automate the scoring of) I'm going to create a related table with valid answers. For the sake of this discussion I will use multiple choice in my implementation. Here is the related table:
    create table quiz_answer( quiz_ansswer_id SERIAL not null primary key, quiz_question_id integer not null references quiz_question(quiz_question_id) on delete cascade, quiz_answer text not null, correct_answer boolean not null default 'false' );

    To create the form here is a sniglet of code ( fetching things from the database is up to you to figure out).

    | | Handwaving here | use strict; use CGI qw/ :all /; my $cgi = new CGI; # This hash reference contains the parameters for # the question... my $question = fetchRandomQueston(); # # This array contains hash references for the answers my @answers = fetchAnswers($question->{quis_question_id}); | | some handwaving here | print $question->{quiz_question},"\n"; print hidden("quiz_question_id", $queston->{quiz_question_id}),br; # There are better ways.. but I'm doing this way # for clarity my %labels = map { $_ -> {quiz_answer_id} => $_ ->{quiz_answer} } @answers; print radio_group( -name=> 'user_answer_rq', -values=> [ map { $_->{quiz_answer_id} } @answers ], -labels => \%labels, -linebreaks => 'true' ),br; print submit;

    I've left a few details out, but you should be able to fill in the blanks by reading the man page for CGI.

    Now once the person in question has selected an answer you can process it fairly easily as follows:

    use CGI; my $cgi = new CGI; my $answer_id = $cgi->param('user_answer_rq'); my $question_id = $cgi->param('quiz_question_id'); my $answer=find_answer_in_db($answer_id}; if ( $answer->{correct_answer} ){ | process accordingly } else { | ditto }

    That oughta give you a good start...


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Organizing Form Input
by andyford (Curate) on Feb 23, 2007 at 21:44 UTC

    OK well lemme try again :)

    If no javascript, then don't you have to make a trip back to the webserver everytime the user adds a field? In that case you can just number them as you create them and there's no need for an array, you just have a lot of parameters.

    The PHP thing looks slick, but it's really just a convenience method. CGI.pm has convenience methods too, check out "FETCHING THE PARAMETER LIST AS A HASH" in the CGI.pm docs. Seems like kinda the same thing.

    non-Perl: Andy Ford

Re: Organizing Form Input
by graff (Chancellor) on Feb 24, 2007 at 16:36 UTC
    Like blue_cowdawg, I'm a little confused about your premise, and I would like to understand it better.

    users are encouraged to fill in a form with a varying number of fields
    I understand "a field on an html form" as being a particular, distinct input element (type-in, radiobutton, etc), so I can't figure out how a form can have a varying number of fields when javascript is disabled. If you meant something else, could you please explain?

    - all of the fields have the same basic premise(being an answer to a question),
    Combining this with the "variable number" issue, what does this imply?
    1. A given question can have one or more answers, or
    2. There can be a variable number of questions, at the user's discretion, each having one answer, or
    3. The user can add questions and have multiple answers on any given question.
    Personally, I would expect a good solution to be different depending on which of those three describes the problem. (But there might be a suitable abstraction that I'm not seeing.)

    Users are able to dynamically add fields(which would also mean dynamically naming them)
    This sort of reiterates the two preceding questions. Does it imply dynamically adding the form input methods, whether or not javascript is enabled? And, does it imply that the user is adding questions, or extra answers to a given question, or both?

    Assuming, as andyford does, that non-javascript users need a round-trip transaction with the server each time they add a new input element to the form, managing the naming seems like a trivial issue. To allow the javascript-enabled users to "economize" on all that back-and-forth traffic, the first problem (seemingly trivial) would simply be to make sure that the javascript uses the same strategy as the server-side cgi script when assigning names to newly added fields, so that the end result is the same no matter what sort of user is involved.

    In either case, it seems like the more challenging issues revolve around how to make all this coherent to the users, so they understand what is expected of them. After that, there might be a strategy question about how to organize the code to reduce the maintenance pains that are bound to arise from having two implementations (with and without javascript) for "the same thing".

    Hmm. That makes me wonder... how hard would it be to write a perl module for creating (some portion of) a web form, such that a perl function could be written to translate that module's code into equivalent, working javascript? (Or maybe there's some way of specifying a form layout, such that it can be used to automatically generate both perl code and javascript code to implement it?)

      Basically, the users are adding questions to a quiz. They are able to type in the text of the question, one right answer, and as many wrong answers as they want to. Instead of just offering up 62 input boxes for wrong answers and saying "fill out as many as you can", I would rather offer just one and an option to "add another answer".

        That doesn't seem so hard, and I could imagine a couple different ways to do this with minimum back-and-forth for non-javascript users -- and no real need for javascript at all, really.

        One way: a specific form/submit button is used to add a question, and there's a type-in to accept the number of possible answers to make available (either including the right answer, or in addition to it), and this defaults to some reasonable value. On submitting this, a second form is given with type-ins for the question itself, and for the requested number of answers.

        Another way: when responding to a request to add a question (no other parameter needed), simply provide three text entry boxes: one for the question, one for the right answer, and a larger (scrollable) one for a list of wrong answers, with instructions on how to mark the boundaries between distinct wrong answers in this box (e.g. use "===" or something like that). So long as you provide a "preview" stage (like PM does), this should work fine.

        In either case, all the components for a new question are submitted at one time; you just need to name and maintain the user/quiz-id and the question-id within the quiz, and based on those, it's simple enough to identify make up identifiers for the "correct answer" string and each of the "wrong answer" strings.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://601746]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (11)
As of 2014-12-19 08:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (75 votes), past polls