SerZKO has asked for the wisdom of the Perl Monks concerning the following question:

Halo Monks, After I got some help here I've continued to work on my script which generates a HTML table by using only CGI.pm. There are at least 1M reasons why I didn't (couldn't) use HTML::Table or some other module for this purpose, so here I am now. I have a following subroutine in my script

sub kundNytt { my @Head = ("Anv. ID", "F\xF6r", "Efter", "Pref", "Bef", "Nytt", "Pr", + "F\xF6r", "Kap"); my $trans = $clrNr; open (TEMP, "<$tempfil") or die "Kan inte \xF6ppna filen $tempfil"; print $qry->start_form(-action => "http://skinnmaskin/cgi-bin/kon.cgi" +); print $qry->table( { Border => 1, Cellpadding => 5, bordercolor =>"#FFFFFF" }, Tr(map { th($_) } @Head), (map { my ($Uid, $Fn, $En, $Pr, $Ank, $Ext, $Or, $Adr) = split /\|/; Tr( td(textfield('UID', $Uid, 6)), td(textfield('FNA', $Fn, 20)), td(textfield('ENA', $En, 35)), td(textfield('PRE', $Pr, 10)), td(textfield('BEF', $Ext, 16)), td(textfield('NYTT', $Ank, 5)), hidden('ADRE', $Addr), td(checkbox_group('GRU',['P', 'F', 'K', 'Ej'],'Ej')), td(checkbox_group('DOL',['Ja', 'Nej'],'Nej')), td(checkbox_group('CMG',['Ja','Nej'],'Nej')), ); } <TEMP>), ); close TEMP; print $qry->hidden('kontor', $trans); print $qry->submit('spara', 'Addera rad'); print $qry->submit('spara', 'Spara'); print $qry->end_form; }
which generates a HTML table from a csv file containing some data where user can change some data and save it back to a file by clicking on "Spara" key. From "CGI programming with Perl" book I could see that when using checkboxes you don't get neither key nor value if checkbox is unchecked. Then I thought it might be a good point to use radio buttons instead. And when I add those lines of code, then I was able to click only one radio button per column and not per row as I expected (as all td's are mapped within Tr) ?!!? What am I missing here ?

Another question is the behaviour of the checkbox group (named GRU in my case) where I would like "Ej" box to be unchecked if any(or more) of the previous boxes are checked - could I use onCheck here and how ? Or even better, is it possible to "make" checkboxes send a name even if they don't have a value (undef) ?

And at last (but not at least), I was trying to add a row to this table by clicking button "Addera rad". My idea was to add en empty row to a file I'm reading the table from and then call subroutine again. And it works so long that "empty" csv row is created in a file. But then, when I recall this subroutine, I get only one (first) row of a file. What am I missing here ? Now, I know that involving DBI is a perfect match for this database which I get in csv format, but for different reasons I'm not able to use it.

Thanks in advance.

Replies are listed 'Best First'.
Re: Problems with CGI script behaviour
by Anonymous Monk on Aug 01, 2012 at 13:28 UTC
    If there are "1M reasons why you can't use a template," and "1M reasons why you can't use CGI," what is there to say? How are we supposed to help you debug this? You are building a complex thing that is one-of-a-kind by your choice, and then one day you will move on and there will be no one in the world to maintain it. Your successor will scrap it all and start again.

      Well, I didn't mean to be boring, but if you want to know the reasons, here comes the representative example:

      1. This is machine we call "BlackBox" which means it was installed and it's been taken care of by our service partner. If we add/change/delete things that come with it (preinstalled of course) that are not covered in service agreement, we loose support. For example - there's neither mySQL nor postgreSQL installed on that machine, and will never be installed (that's the agreement).

      2. Vendor of that "blackbox" is a huge multinational company that probably would eat (both our service partner and us) us if we change something they set up.

      3. We don't have access rights to e.g. make and install own perl distribution.

      That basically means that we can use everything that is installed, but install/upgrade/add/change/delete without service partner agrees is strictly forbidden (according to SLA). Now, we can and would like to use some things that already are installed (file with data, Perl distribution, etc.), but those are restrictions which I described as 1M reasons. I saw this as a challenge (although I'm not a programmer at all, even if my job requires a lot of C and shell scripting knowledge) and didn't mean to offend anyone...

Re: Problems with CGI script behaviour
by Anonymous Monk on Aug 01, 2012 at 17:09 UTC

    My advice: throw CGI.pm's stupid HTML wrappers away and write HTML directly. They are not worth it. There's no black box in front of you if you bother to write the forms directly. The only thing CGI.pm is useful for is accessing HTTP headers and query params. [1] Anyway, I'll let you on a secret. The #1 debugging tool in web programming. Ctrl-U (View Source).

    Then I thought it might be a good point to use radio buttons instead. And when I add those lines of code, then I was able to click only one radio button per column and not per row as I expected (as all td's are mapped within Tr) ?!!? What am I missing here ?

    Radio buttons are grouped based on their name attribute.

    Another question is the behaviour of the checkbox group (named GRU in my case) where I would like "Ej" box to be unchecked if any(or more) of the previous boxes are checked - could I use onCheck here and how ? Or even better, is it possible to "make" checkboxes send a name even if they don't have a value (undef) ?

    If you want only one of them to be checked, use radio buttons. oncheck is javascript and is dependent on the client browser to work. (Bad idea in my opinion, but seeing the current trends in web development, I'm in the minority.)

    Checkboxes (or radio buttons) aren't submitted with the form if none are selected. You can default your params like this: $q->param(GRU => "Ej") unless $q->param('GRU');

    I was trying to add a row to this table by clicking button "Addera rad". My idea was to add en empty row to a file I'm reading the table from and then call subroutine again. And it works so long that "empty" csv row is created in a file. But then, when I recall this subroutine, I get only one (first) row of a file. What am I missing here ?

    Du måste addera din rad to the loop. Your loop is dependent on the file handle TEMP currently. It won't generate a single row after that. I'm afraid I'm not sure how to help there since the code looks pretty much a mess thanks to CGI.pm. (There's a map where usually a for loop would be.)

    [1] Okay, I'll give it one more. It's okay for doing form prefills.

      Your loop is dependent on the file handle TEMP currently. It won't generate a single row after that. I'm afraid I'm not sure how to help there since the code looks pretty much a mess thanks to CGI.pm. (There's a map where usually a for loop would be.)

      I suppose something as simple as changing the map from map { ... } <TEMP> to map { ... } <TEMP>, "" (where "" is a dummy CSV row) would work but then it would only add one row and if the user wants to add multiple you would have to keep count on how many are needed and $ENV{DEITY}, I hate doing user interfaces with HTML forms. (But I hear HTML::FormFu might be pleasant to use.)

      Hej and thanks for your reply.

      I'll try adding a row in a loop, although my only problem with this is rewriting the table (read the changed file again gives me back one more row, but with data from only first row).

      But when you say that radio buttons are grouped by their name, shouldn't they be that per table row and not column? I was hoping to get following result when I press "Spara" button :
      UID= UID= UID=CAME01 FNA= FNA= FNA=Carin ENA= ENA=S%E4k ENA=Plan PRE=%280157-%29 PRE=%280157-%29 PRE= BEF= BEF= BEF=0150-75385 NYTT=69090 NYTT=69099 NYTT= ADRE=Norra%20Kungsgatan%204B ADRE=Norra%20Kungsgatan%204B ADRE=Stortorget%201 GRU=P GRU=Ej GRU=Ej DOL=Nej DOL=Nej DOL=Nej CMG=Ja CMG=Ja CMG=Ja
      and instead I get only one DOL and CMG entry:
      UID= UID= UID=CAME01 FNA= FNA= FNA=Carin ENA= ENA=S%E4k ENA=Plan PRE=%280157-%29 PRE=%280157-%29 PRE= BEF= BEF= BEF=0150-75385 NYTT=69090 NYTT=69099 NYTT= ADRE=Norra%20Kungsgatan%204B ADRE=Norra%20Kungsgatan%204B ADRE=Stortorget%201 GRU=P GRU=Ej GRU=Ej DOL=Nej CMG=Ja

      Any suggestion ?

      P.S. Thanks for the great tip with unless. I should have come up to that myself...D.S.

        They are grouped by name. They don't care one bit how the table is laid out beneath them, all the care about is the <input name="something">. Really, check the HTML source to debug.

        But, I think your problem might be that you are having multiple boxes set as checked when generating the HTML.

        ...row1 <td><label><input type="checkbox" name="DOL" value="Ja" />Ja</label> +<label><input type="checkbox" name="DOL" value="Nej" checked="checked +" />Nej</label></td> ...row2 <td><label><input type="checkbox" name="DOL" value="Ja" />Ja</label> +<label><input type="checkbox" name="DOL" value="Nej" checked="checked +" />Nej</label></td>

        So the name attribute matches but there are multiple checked. The browsers are required to pass each and every checked checkbox back. Did you want to use radio buttons or check buttons? (Even with radio buttons you might have these kinds of problems if the HTML you supply has multiple checked.)

        I'm not really sure what you want since the code currently is fairly complex. You would benefit much if you made a new SOPW post with the bare minimum of code relevant to your problems, preferably one at a time. That, or create a HTML page with mere radio buttons / checkboxes and muck around it until it works. Then try to integrate that with your existing code.

        BTW, having two submit buttons with the same name (spara) doing different things (saving and adding rows) is likely to lead to problems later on.

Re: Problems with CGI script behaviour
by aaron_baugher (Curate) on Aug 01, 2012 at 14:51 UTC

    I'  li e to help, but for m ny re  on  I  m un ble to u e the letter   ,  ,  , or  .
    

    Aaron B.
    Available for small or large Perl jobs; see my home node.

      No need to be rude Aaron. Please read my answer to Anonimous Monk first and judge then.