Formulieren

Leerdoelen

Na het bestuderen van dit hoofdstuk wordt van je verwacht dat je:

  • een formulier in html kunt maken
  • tekst invoervelden en submit knoppen kunt maken
  • weet wat request-parameters zijn
  • hoe je parameters kunt opvragen
  • weet hoe je strings naar getallen kunt "parsen"
  • weet hoe je een Exception in java kunt afvangen en kunt gebruiken voor bijvoorbeeld een foutmelding
  • hoe je in html verborgen (hidden) invoervelden kunt maken en gebruiken

In HTML kun je formulieren maken met de form tag. Een html formulier met één invoerveld en één knop ziet er als volgt uit:

<form action="doelpagina.jsp" method="get">
    <input type="text" name="tekst_input_1">
    <input type="submit" name="knop_1" value="Ok">
</form>

Uitleg

<form action="doelpagina.jsp" method="get">
    <input type="text" name="tekst_input_1">
    <input type="submit" name="knop_1" value="Ok">
</form>

action

Bepaalt naar welke pagina het formulier toe wordt gestuurd. Het gebeurt vaak dat bezoeker naar dezelfde pagina wordt teruggeleid.

<form action="doelpagina.jsp" method="get">
    <input type="text" name="tekst_input_1">
    <input type="submit" name="knop_1" value="Ok">
</form>

method: get of post

Als een formulier wordt opgestuurd, dan worden de waardes van het formulier als parameters meegezonden. Indien voor method "get" wordt gekozen, dan worden de parameters in de url meegestuurd. Bovenin de adresbalk van je browser zie je dat achter de doelpagina (bijvoorbeeld eindigend op .jsp) een vraagteken met daarachter waardes worden toegevoegd. Verschillende waardes worden gescheiden met &. Als bovenstaand formulier zou worden opgestuurd, dan zou je url twee parameters meekrijgen en er als volgt uitzien:

http://doelpagina?tekst_input_1=[invoer gebruiker]&knop_1=Ok

Als je niet wilt dat de parameters in je url komen te staan, bijvoorbeeld omdat er vertrouwelijke info wordt verstuurd en je niet wilt dat die zichtbaar wordt, dan kun je de method "post" gebruiken.

<form action="doelpagina.jsp" method="get">
    <input type="text" name="tekst_input_1">
    <input type="submit" name="knop_1" value="Ok">
</form>

input: text

Dit is een invoerveld waar de bezoeker iets in kan vullen. Het invoerveld krijgt een naam. Dit is de naam van de parameter die wordt meegestuurd

<form action="doelpagina.jsp" method="get">
    <input type="text" name="tekst_input_1">
    <input type="submit" name="knop_1" value="Ok">
</form>

input: submit

Dit is een knop. Als gebruiker op deze knop klikt, wordt het formulier naar de doelpagina gestuurd. Ook een knop krijgt een naam.

Het formulier verwerken

In je doelpagina moet je de waardes eerst opvragen als je er iets mee wilt doen. Dit doe je als volgt:

<%
//check welke knop bezoeker heeft geklikt
if (request.getParameter("knop_1") != null) {
    //haal de parameter(s) binnen
    String invoer = request.getParameter("tekst_input_1");
}
%>

Opdracht 8

Breid opdracht 6 uit zodat de bezoeker van de webpagina door een getal in te voeren bepaalt welke tafel hij te zien krijgt. Er wordt pas een tafel zichtbaar nadat de de gebruiker op de knop heeft gedrukt. Bij foute invoer (geen geheel getal) wordt er naast het invoerveld een rode waarschuwingstekst vertoond. Probeer onderstaande uitwerking en let goed op de URL in de adresbalk van je browser voor- en nadat je op de knop hebt geklikt. Wat is er veranderd?

Aanwijzingen

De methode request.getParameter("naam") geeft altijd een string waarde. Om er mee te kunnen rekenen moet de string geparsed worden, in dit geval naar een integer (zie Inleiding Java).

Als gebruiker per ongeluk een letter in plaats van een getal heeft ingevuld, dan treedt er een zogenaamde NumberFormatException op. Om te vermijden dat je programma crasht, moet je deze "afvangen". Gebruik de Exception om een foutmelding in het scherm te zetten. Probeer maar eens uit in onderstaande uitwerking (voer een letter in in plaats van een cijfer).

Kies een tafel


Formulier

Maak eerst het formulier. Dit bestaat uit twee input elementen: een tekstveld en een knop. Daar tussenin moet nog een foutmelding komen voor het geval de gebruiker een verkeerde waarde invoert. Daarover later meer.

<form action="index.jsp" method="get">
	<input type="text" name="getal">
           
	<div class="fout">
		<%= foutboodschap %>
	</div>
	<div class="knop">
		<input type="submit" name="knop" value="Ok">
	</div>
</form>

Uitleg

In de <form> tag kun je met action="url" aangeven naar welke pagina de gebruiker moet worden geleid wanneer hij op de knop drukt. In dit geval wordt de gebruiker naar dezelfde pagina terug geleid.

Het tekstveld en de knop krijgen beide een naam met: name="...". Als de gebruiker op de knop drukt, worden er parameters aangemaakt met de namen van de input velden en hun waardes die aan het verzoek (request) voor de pagina worden meegegeven. De knop krijgt een standaardwaarde "Ok". De waarde van getal is afhankelijk van wat de gebruiker in het tekstveld invult. Als je op de knop klikt zie je in de adresbalk van je browser na de verwijzing naar het pagina-bestand (eindigend op .jsp) een vraagteken verschijnen met daarachter de namen van de input velden en hun waardes, gescheiden met &. Na klikken op de knop wordt de url aangevuld met twee parameters:
?getal=&knop=Ok

De knop krijgt als waarde (value) Ok mee en getal heeft in dit geval geen waarde. Blijkbaar heeft de gebruiker niets ingevuld.

JSP

Met behulp van JSP maken we de benodigde variabelen en kennen waardes toe met behulp van de - met de request meegezonden - parameters. De waardes van parameters kunnen worden opgevraagd met:
request.getParameter("naam van het input-veld")

<% 
int getal = 0;
boolean geklikt = false;
String strGetal;
String foutboodschap = "";

if (request.getParameter("knop") != null) {
    strGetal = request.getParameter("getal");
    try {
        getal = Integer.parseInt(strGetal);
        geklikt = true;
    }
    catch(NumberFormatException exc) {
        
        foutboodschap = "U moet een geheel getal invoeren!";
    }
    finally {
        
    }
}
%>

Uitleg

We willen alleen dat er een tafel zichtbaar wordt nadat de gebruiker op de knop heeft gedrukt. Dit kunnen we aangeven met een aanroep naar de parameter "knop". Deze krijgt pas de waarde "Ok" nadat er op de knop is geklikt. Tot dan is hij null. Dit kunnen we gebruiken als voorwaarde in een if-statement.

int getal krijgt zijn waarde als door de gebruiker een geldig getal is ingevuld. Hiermee wordt de tafel straks gemaakt.

boolean geklikt gaan we gebruiken om te bepalen of er wel of niet een tafel wordt vertoond. Maak hem aanvankelijk false zodat er geen tafel wordt vertoond als gebruiker op de pagina komt.
Pas nadat gebruiker een geldig geheel getal heeft ingevoerd maken we hem true.

strGetal: Wanneer een gebruiker een getal in een tekstvak invoert moet dit getal worden geconverteerd van String naar int. Dit doen we met: getal = Integer.parseInt(strGetal). De static methode parseInt() van de klasse Integer gooit een zogenaamde NumberFormatException op wanneer de gebruiker een ongeldige waarde invoert. Deze kunnen we "opvangen" (catch) in een try...catch blok. We gebruiken de exception om de foutboodschap aan te maken. Wanneer het ingevoerde getal kan worden geconverteerd naar een int, geven we boolean geklikt de waarde true. Daarmee geef je het groene licht voor het maken van de tafel.

Voor de tafel zelf gebruiken we een for-lus.

<% if (geklikt) { 
	for (int i = 1; i <= 10; i++) { %>
		<%= i %> x <%= getal %> = <%= i * getal %> <br>
	<% } 
} %>

Met behulp van CSS code zorgen we er tenslotte voor dat de waarschuwingstekst rood wordt, iets kleiner dan de andere tekst naast het invoervak wordt geplaatst. Een div is van zichzelf een blok element. Blok elementen worden standaard van boven naar beneden onder elkaar geplaatst. Inline elementen worden daarentegen van links naar rechts naast elkaar geplaatst. In CSS kun je dit veranderen.

div.fout {
	color: red;
	font-size: 0.8em;
	display: inline;
}

Opdracht 9

Breid de vorige opdracht uit zodat de bezoeker met twee extra knoppen ("vorige" en "volgende") de tafel met één kan verhogen of verlagen (zie voorbeeld).

Aanwijzingen

Soms moet met een formulier een waarde worden meegestuurd die je programma nodig heeft, maar die je bezoeker niet hoeft te zien. Dit kun je doen met een verborgen input veld. De waarde (value) kan bijvoorbeeld een jsp-expressie zijn.

<form action="doelpagina.jsp" method="get">
    <input type="text" name="tekst_input_1">
    <input type="submit" name="knop_1" value="Ok">
    <input type="hidden" name="naam" value="<%= eenWaarde %>">
</form>

Kies een tafel


Je kunt onder de tafel die je hebt gemaakt in opdracht 8 een formulier met twee knoppen "min" en "plus" toevoegen. In je Java code geef je aan dat getal moet worden verlaagd respectievelijk verhoogd wanneer gebruiker op één van de twee knoppen drukt. Het probleem dat zich nu voordoet is dat het oorspronkelijke getal vergeten is wanneer de gebruiker een nieuw request indient door op één van de knoppen te klikken. Om dit probleem op te losssen maak je gebruik van een "verborgen" invoerveld die de waarde van getal meegeeft aan het request.

<% if (geklikt) { %>
 <h3>De tafel van <%= getal %></h3>
 	<% for (int i = 1; i <= 10; i++) { %>
     	<%= i %> x <%= getal %> = <%= i * getal %> <br>
 	<% } %>
 	<form action="index.jsp" method="get">
 		<input type="hidden" name="getal" value="<%= getal %>">
 		<input type="submit" name="min" value=" < " >
 		<input type="submit" name="plus" value=" > " >
 	</form>
 
<% } %>

Nu kun je je Java code uitbreiden zodat de knoppen doen wat ze moeten doen.

<%
boolean geklikt = false;
String strGetal;
int getal = 0;
String foutboodschap = "";
if (request.getParameter("knop") != null || 
	request.getParameter("min") != null ||
	request.getParameter("plus") != null)

{
		strGetal = request.getParameter("getal");
		try {
			getal = Integer.parseInt(strGetal);
			geklikt = true;
		}
		catch(NumberFormatException e) {
			foutboodschap = "U moet een geheel getal invoeren!";
		}
		finally {
			//doe niets
		}
		
		if (request.getParameter("min") != null) {
			getal = getal - 1;
		}
		else if (request.getParameter("plus") != null) {
			getal = getal + 1;
		}
}
%>

Opdracht 10

Schrijf een webpagina waarin de graden in Celsius worden omgerekend naar graden in Fahrenheit. Het formulier op de pagina bevat een tekstvak en een knop. De formule voor de conversie is: Fahrenheit = Celsius * 1.8 + 32. De uitkomst wordt in een andere pagina gegeven waarop ook de link staat om terug te keren naar de vorige pagina. De uitkomst van de berekening moet worden weergegeven in een geheel getal. Voor een juiste afronding kun je één van de twee static methoden round() van de Java klasse Math gebruiken. Bij beide methoden zit echter een addertje onder het gras!


Om er voor te zorgen dat de gebruiker naar een andere pagina wordt geleid als zij op de knop klikt, moet je een nieuwe .jsp pagina aanmaken en in het formulier bij action="." hiernaar verwijzen. In dit voorbeeld heet de jsp pagina fahrenheit.jsp en bevindt zich in dezelfde map als de oorspronkelijke pagina.

<form action="fahrenheit.jsp" method="get">
	<input type="text" name="celsius">
	<input type="submit" value="Ok">
</form>

In de fahrenheit.jsp pagina maak je de attributen aan die je nodig hebt:

  • een int celsius
  • een int fahrenheit
  • eventueel een String tekst die kan dienen als tekst met de conversie, of als foutmelding indien gebruiker geen goede invoer (geheel getal) heeft ingevoerd
<%
int celsius;
int fahr;
String tekst = "";
try {
	celsius = Integer.parseInt(request.getParameter("celsius"));
	fahr = Math.round(celsius * 1.8f + 32);
	//alternatief
	//fahr = (int) Math.round(celsius * 1.8 + 32);
	tekst = celsius + " graden Celsius is " + fahr + " graden Fahrenheit";
}
catch(NumberFormatException e) {
	tekst = "Foute invoer, u moet een geheel getal invoeren";
}
finally {
	
}
%>
<h2>Conversie van Celsius naar Fahrenheit</h2>
<p><%= tekst %></p>

De methode round() van de klasse Math

Zoek in de Java API de klasse Math. Bij de methoden zie je dat er twee methoden round() bestaan. Het bestaan van twee methoden met dezelfde naam, maar met verschillende parameters noemen we overloading.

de methode round van klasse Math

De eerste methode vereist als parameter een double, en heeft als terugkeerwaarde een long. Een long is de 64-bit grote broer van int. Om van een long een int te maken moet je hem typecasten (zie code). Typecasten is alleen nodig wanneer er eventueel informatie verloren kan gaan. Je geeft als het ware te kennen aan de compiler dat je als programmeur accepteert dat er eventueel informatie verloren gaat.

De tweede methode heeft als terugkeerwaarde een int, maar vraagt als parameter een float. De float is het kleine - wat minder precieze - 32-bit broertje van double. Als je in Java een decimaal gebruikt, gaat Java er van uit dat je een double wilt gebruiken. Om een float te gebruiken kun je een f achter de decimaal zetten.

Opdracht 11

Schrijf een webpagina waarin de bezoeker getallen kan invoeren en bijgehouden wordt welk getal het hoogst is en welk getal het laagst is.

Hoogste en laagste

Voer een geheel getal in



Je hebt twee int variabelen nodig om te kunnen bepalen wat het laagste en het hoogste getal is dat door de gebruiker is ingevoerd. Om deze een initiële waarde te geven kun je gebruik maken van respectievelijk Integer.MAX_VALUE en Integer.MIN_VALUE. Dezen geven de maximale respectievelijk minimale waarden die een int in Java aan kan nemen. Let op: dit zijn geen methoden maar zogenaamde "static" attributen die meteen op de klasse kunnen worden aangeroepen. Eerder hebben we een dergelijk attribuut gebruikt bij de klasse Calendar in opdracht 3. Bekijk de klasse Integer in de API. Je vindt de attributen onder "Field Summary".

Net als in opgave 9 kun je in deze opgave ook met verborgen inputvelden werken om de laagste en de hoogste waarde opnieuw aan het request mee te geven.

  <body>
      
      <%
      int laagste;
      int hoogste;
      String waarschuwing = "";
      if (request.getParameter("laagste") == null) {
          laagste = Integer.MAX_VALUE;
          hoogste = Integer.MIN_VALUE;
      }
      else {
          laagste = Integer.parseInt(request.getParameter("laagste"));
          hoogste = Integer.parseInt(request.getParameter("hoogste"));
      }

      try {
          int invoer = Integer.parseInt(request.getParameter("getal"));
          if (invoer < laagste) {
              laagste = invoer;
          }
          if (invoer > hoogste) {
              hoogste = invoer;
          }
        }
      catch(NumberFormatException e){
          waarschuwing = "U moet een geheel getal invoeren";
      }
      finally {

      }

%>
      <h1>Hoogste en laagste</h1>
      <form action="index.jsp" method="get">
          <input type="text" name="getal">
          <input type="submit" name="knop" value="Ok">
          
          <input type="hidden" name="hoogste" value="<%= hoogste %>">
          <input type="hidden" name="laagste" value="<%= laagste %>">
          
          <% if (request.getParameter("knop") != null) { %>
          <p><%= waarschuwing %> </p>
          <% if (laagste != Integer.MAX_VALUE) { %>
              <p>Laagste getal: <%= laagste %> </p>
              <p>Hoogste getal: <%= hoogste %> </p>
          <% }
          }%>

      </form>
  </body>

Opdracht 12

Schrijf een webpagina waarin de graden in Fahrenheit worden omgerekend naar graden in Celsius of omgekeerd. De webpagina bevat twee tekstvelden en de knop Omrekenen. Als er op de knop Omrekenen wordt geklikt wordt de uitkomst van de berekening in het juiste tekstvak gezet en wordt het andere tekstvak leeggemaakt. De formules zijn: Fahrenheit = Celsius * 1.8 + 32 en Celsius = (Fahrenheit - 32) / 1.8. Er is altijd een tekstvak met invoer en een tekstvak dat leeg is. Zo weet de pagina of er van Celsius naar Fahrenheit of van Fahrenheit naar Celsius moet worden omgerekend. Maak naast JSP gebruik van HTML en CSS bij het uitvoeren van deze opdracht.

Fahrenheit en Celsius omrekenen

Graden

Celsius

Fahrenheit

<body>
  <%
  String celsValue = "";
  String fahrValue = "";
  int cels;
  int fahr;
  String warning = "";
  if (request.getParameter("knop") != null) {
    try {
      if (!request.getParameter("cels").equals("") &&
       !request.getParameter("fahr").equals("")) {
        warning = "Voer slechts één waarde in!";
      }
      else if (!request.getParameter("cels").equals("")) {
        cels = Integer.parseInt(request.getParameter("cels"));
        fahr = Math.round(cels * 1.8f + 32);
        fahrValue += fahr;
      }
      else if (!request.getParameter("fahr").equals("")) {
        fahr = Integer.parseInt(request.getParameter("fahr"));
        cels = Math.round((fahr - 32)/1.8f);
        celsValue += cels;
      }
    }
    catch(NumberFormatException e) {
      warning = "Voer een geheel getal in";
    }
   }
   %>
        
  <h1>Fahrenheit en Celsius omrekenen</h1>
  <form action="index.jsp" method="get">
    <table id="graden">
      <tr>
        <th>Celsius</th>
        <th>Fahrenheit</th>
      </tr>
      <tr>
        <td><input type="text" name="cels" value="<%=celsValue%>"></td>
        <td><input type="text" name="fahr" value="<%=fahrValue%>"></td>
        <td><input type="submit" name="knop" value="Omrekenen"></td>
      </tr>
      <% if (request.getParameter("knop") != null) { %>
      <tr>
        <td colspan="2" class="fout"><%= warning %></td>
      </tr>
      <% } %>
    </table>

  </form>
</body>

Uitleg

In deze uitwerking gebruiken we 2 int variabelen om de berekening van Celsius en Fahrenheit te maken. Daarnaast gebruiken we twee Strings om de tekstvakken een waarde (value) te geven.

Je mag nooit twee Strings met elkaar vergelijken met == of !=. In plaats daarvan gebruik je de methode equals(Oject obj). Deze geeft "true" terug als de objecten hetzelfde zijn. Met het uitroepteken kun je true en false omkeren.

De coderegel if (!request.getParameter("cels").equals("")) { betekent dus:
Geef "true" terug als de parameter met de naam "cels" niet gelijk is aan een lege String...

Opdracht 13

Schrijf een webpagina die een rekenmachine bevat. De rekenmachine kan optellen, aftrekken, vermenigvuldigen en delen. De bezoeker van de webpagina kan twee getallen invoeren en drukt op een knop om de gewenste berekening te laten uitvoeren. De uitkomst van de berekening wordt in het eerste tekstvak getoond zodat de gebruiker met de uitkomst verder kan rekenen. De rekenmachine zou er als volgt uit kunnen zien:

Rekenmachine

Eerste getal

Tweede getal