# JSF-Formular mit DataTabel



## PeterRRR (7. Apr 2009)

Hallo!

Ich hab in JSF ein Formular, das mit h:dataTabel gefüllt wird. DataTabel liest seine Zeilen aus einer ArrayList aus.
Das ganze sieht dann folgendermaßen aus:



> [ outputText: Text ]   [inputText: Anzahl]   [commandButton: Enter]



also etwa:


> Äpfel        5   ENTER
> Birnen       2   ENTER
> Bananen    4   ENTER



Der Benutzer soll im Eingabefeld eine Anzahl eingeben können und mit Klick auf den Enter-Button wird die Anzahl dann im JavaBean gesetzt (setter).

Das Problem ist aber, dass es vollkommen egal ist, welcher ENTER-Button geklickt wird. D.h. wenn ich beispielsweise bei "Äpfel" 0 eingebe und den ENTER-Button von Bananen klicke wird trotzdem bei den Äpfeln auf 0 gesetzt. Ich möchte es aber so haben, dass jeder einzelne ENTER-Button nur für die eine entsprechende Zeile gilt. Also bei dem eben genannten Beispiel sollte es dann so sein, dass ein Klick auf den Bananen-ENTER-Button die Äpfel NICHT verändert. 

Ich hoffe das war einigermaßen verständlich. Nur hab ich leider keine Ahnung wie ich das umsetzen könnte, ich hab schon so viel herumprobiert aber bin noch zu keiner Lösung gekommen. :bahnhof:
Wer kann helfen? Danke schon jetzt dafür!

lg
Peter


----------



## gex (7. Apr 2009)

Damit du das Objekt dieser Zeile erhälst kannst du params benutzen:
Wie kann ich einen Parameter von einer JSF-Seite an einen ActionListener übergeben? - Forum Fachinformatiker.de

gruss


----------



## PeterRRR (9. Apr 2009)

Danke erstmal für die Antwort. Das mit den Parametern wusste ich schon, aber wie genau wende ich das ganze dann in meinem Fall an? Ich kann zwar mit einem ActionListener dann eine Methode aufrufen, aber wie komme ich dann in der Java-Klasse an den im Input-Feld eingegebenen Wert um die Anzahl richtig zu setzen? Ich hab hier mal die Code-Beispiele für die JSP, das Bean und die Früchte-Klasse wobei ich die betreffende Stelle im ActionListener in der Fruchtliste.java markiert habe:

*fruechte.jsp* (Auszug)

```
<f:view>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><h:outputText value="Frucht-Demo" /></title>
</head>
<body>
    <h:form>
        <h:dataTable value="#{fruechte.liste}" var="myFrucht">
            <h:column>
                <h:outputText value="#{myFrucht.sorte}" />
            </h:column>
            <h:column>
                <h:inputText id="myInput" size="3" value="#{myFrucht.anzahl}" />
            </h:column>
            <h:column>
                <h:commandButton value="ENTER" actionListener="#{fruechte.myActionlistener}">
                    <f:param id="myParam" name="myParam" value="#{myFrucht.sorte}" />
                </h:commandButton>
            </h:column>
        </h:dataTable>
    </h:form>
</body>
</html>
</f:view>
```
*Fruchtliste.java (Bean)*

```
package test;

import java.util.ArrayList;
import java.util.Map;

import javax.faces.context.FacesContext;

public class Fruchtliste implements java.io.Serializable{

    private static final long serialVersionUID = 590223103993112954L;
    private ArrayList<Fruechte> liste = new ArrayList<Fruechte>();
    
    public Fruchtliste()
    {
        liste.add(new Fruechte("Äpfel", 5));
        liste.add(new Fruechte("Birnen", 2));
        liste.add(new Fruechte("Bananen", 4));
    }
    
    public ArrayList<Fruechte> getListe() {
        return liste;
    }
    public void setListe(ArrayList<Fruechte> liste) {
        this.liste = liste;
    }
    
    public void myActionlistener(javax.faces.event.ActionEvent e)
    {
        Map<String, String> myMap=FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        String param= (String) myMap.get("myParam").toString();
        
        for(Fruechte f:liste)
        {
            if(f.getSorte().equals(param))
            {
      [COLOR=Red]          [B]??? was gehört hier rein ???[/B][/COLOR]
            }
        }
    }
}
```
*Fruechte.java*

```
package test;

public class Fruechte{

    private static final long serialVersionUID = 4701765865134493122L;
    private String sorte;
    private int anzahl;
    
    public Fruechte(String s, int a)
    {
        setSorte(s);
        setAnzahl(a);
    }
    
    public String getSorte() {
        return sorte;
    }
    public void setSorte(String sorte) {
        this.sorte = sorte;
    }
    public int getAnzahl() {
        return anzahl;
    }
    public void setAnzahl(int anzahl) {
        this.anzahl = anzahl;
    }
}
```
Wäre toll, wenn mir da jemand nochmal weiterhelfen könnte, danke dafür schon jetzt!

lg Peter


----------



## gex (10. Apr 2009)

Hi

Hmm, habe dir wohl den falschen Link gesendet.
Der folgende Ansatz sollte funktionieren (ungetestet).


```
<h:commandButton value="ENTER" actionListener="#{fruechte.myActionlistener}">
    <f:attribute name="myAttr" value="#{myFrucht}" />
</h:commandButton>
```

und 

```
public void myActionlistener(javax.faces.event.ActionEvent e)
    {
	Fruechte frucht = (Fruechte) e.getUIComponent().getAttributes().get("myAttr");
	frucht.getAnzahl();
    }
```


----------



## PeterRRR (10. Apr 2009)

Grundsätzlich funktioniert das schon (es heißt nur "e.getComponent()....."), nur bringt mir das auch nicht wirklich das was ich ja eigentlich wollte. Außerdem bekomme ich, wenn ich bei deinem Codebeispiel mit getAnzahl() oder getSorte() die jeweiligen Werte mit println ausgeben will immer eine Null Pointer Exception. Aber darum ist es ja nie gegangen.
Am Ausgangsproblem, der Möglichkeit jede Zeile nur mit einem einzigen zugehörigen Button ansprechen zu können, hat sich trotzdem nichts geändert.
Aber trotzdem danke für die Mühe.

lg
Peter


----------



## gex (11. Apr 2009)

Ähm, was möchtest du denn haben, resp. was verstehst du unter "ansprechen"?
Du erhälst ja genau diese Zeile? Oder willst du, dass nur die Werte dieser Zeile ins Model (BackingBean) übernommen werden?


----------



## PeterRRR (12. Apr 2009)

Ja wie schon im ersten Beitrag geschrieben möchte ich eben, dass genau EIN Button zu jeder Zeile gehört und die Zeile bzw. das Eingabefeld in der Zeile nur auf genau diesen Button reagiert.

Momentan ist es ja so, dass ich z.B. ins Eingabefeld in der ersten Zeile eine Zahl eingebe und auf z.B. den letzten Button klicke und der Wert wird dennoch in der ersten Zeile übernommen. So sollte es aber eben nicht sein, sondern so, dass das Eingabefeld der ersten Zeile auch nur auf den Button in der ersten Zeile reagiert, das Eingabefeld in der zweiten Zeile auf den Button in der zweiten Zeile usw. Alles andere wäre meiner Meinung nach ja irgendwie unlogisch. Ich hab auch schon probiert, jede Zeile der Tabelle als eigenes Formular zu gestalten, das funktioniert aber nicht wirklich (kann man in dataTabel keine Formulare verschachteln?)

lg
Peter


----------



## gex (12. Apr 2009)

Na der Button gehört doch zu einer Zeile (optisch, sowie im Component-Tree) 

Das hängt mit dem JSF Lifecycle zusammen: The Life Cycle of a JavaServer Faces Page

JSF arbeitet prinzipiell über die ganze View, somit werden alle Werte einer View übernommen, ausser es wird mit 
bestimmten AJAX Components gearbeitet (IceFaces, Richfaces), da gibt es Möglichkeiten nur Teilbereiche zu übertragen.


----------



## PeterRRR (16. Apr 2009)

Danke, das wusste ich nicht, dass das nicht anders funktioniert. Aber danke für den Hinweis und den Link.

lg
Peter


----------

