JSF wyświetlenie ArrayList za pomocą separatora #{..}

1

Wiam serdecznie,

chciałabym się zapytać jak wyświetlić listę za pomocą separatora #{...} w JSF? Mój kod pliku index.xhtml przedstawia się następująco:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h3>#{msgs.naglowek}</h3>
            <p>
                <h:outputFormat value="#{msgs.aktualnyWynik}">
                    <f:param value="#{quizBean.wynik}"/>
                </h:outputFormat>
            </p>
            <p>#{msgs.zgadnacNext}</p>  

            <p>#{quiz.aktualny.sekwencja}</p> 

            <p>#{msgs.odpowiedz}
                <h:inputText value="#{quizBean.odpowiedz}"/>
            </p>  
            <p><h:commandButton value="#{msgs.next}"/></p>
        </h:form>
    </h:body>
</html>

Klasy które odpowiadają za wyświelenie elementów tablicy , przedstawią się następująco:

package corejsf;

import java.io.Serializable;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class QuizBean implements Serializable {

    private ArrayList<ProblemBean> problems = new ArrayList<ProblemBean>();
    private int aktualnyIndeks;
    private int wynik;

    public QuizBean() {
        problems.add(new ProblemBean(new int[]{3, 1, 4, 1, 5}, 9));
        problems.add(new ProblemBean(new int[]{1, 1, 2, 3, 5}, 8));
        problems.add(new ProblemBean(new int[]{1, 4, 9, 16, 25}, 36));
        problems.add(new ProblemBean(new int[]{2, 3, 5, 7, 11}, 13));
        problems.add(new ProblemBean(new int[]{1, 2, 4, 8, 16}, 32));

    }

    public void setProblems(ArrayList<ProblemBean> nowaWartosc) {
        problems = nowaWartosc;
        aktualnyIndeks = 0;
        wynik = 0;
    }

    public int getWynik() {
        return wynik;
    }

    public ProblemBean getAktualny() {

        return problems.get(aktualnyIndeks);
    }

    public String getOdpowiedz() {
        return "";
    }

    public void setOdpowiedz(String nowaWartosc) {

        try {
            int odpowiedz = Integer.parseInt(nowaWartosc.trim());
            if (getAktualny().getRozwiazanie() == odpowiedz) {
                wynik++;
            }

            aktualnyIndeks = (aktualnyIndeks + 1) % problems.size();
        } catch (NumberFormatException ex) {
        }


    }
}
package corejsf;

import java.io.Serializable;
import java.util.ArrayList;

class ProblemBean implements Serializable {

    private ArrayList<Integer> sekwencja;
    private int rozwiazanie;

    public ProblemBean() {
    }

    public ProblemBean(int[] values, int rozwiazanie) {
        sekwencja = new ArrayList<Integer>();
        for (int i = 0; i < values.length; i++) {
            sekwencja.add(values[i]);
        }
        this.rozwiazanie = rozwiazanie;
    }

    public ArrayList<Integer> getSekwencja() {
        return sekwencja;
    }

    public void setSekwencja(ArrayList<Integer> nowaWartosc) {
        sekwencja = nowaWartosc;
    }

    public int getRozwiazanie() {
        return rozwiazanie;
    }

    public void setRozwiazanie(int nowaWartosc) {
        this.rozwiazanie = nowaWartosc;
    }
}

Metoda getAktualny() powinna spowodowac wyświelenie, ale jednak tego nie robi. Próbowałam przez :

  <p>#{QuizBean.sekwencja}</p> 
  <p>#{QuizBean.aktualny}</p> 
  <p>#{QuizBean.aktualny.sekwencja}</p> 

ale bez rezultatu :(

Będę bardzo wdzieczna o wskazówki jak wyświetlić listę w taki sposób:

[3, 1, 4, 1, 5]

0

Skoro chcesz zwrócić ArrayList, to musisz mieć kontrolkę, która to obsłuży iteracyjnie. W samym JSF to będzie dataTable i właściwie powinno wystarczyć. Spróbuj:
<h:dataTable id="table1" value="#{quiz.aktualny.sekwencja}" var="item">
<f:facet name="header">
<h:outputText value="Lista liczb w sekwencji" />
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Liczby" />
</f:facet>
<h:outputText value="#{item}" />
</h:column>
</h:dataTable>

0

gdy wprowadziłam jak zaproponowałeś

@ManagedBean(name="quiz")

pojawił się błąd :

/index.xhtml @19,72 value="#{quiz.aktualny.sekwencja}": Property 'sekwencja' not readable on type java.util.ArrayList

spróbuję wiec zamienić całą tablicę na String, dobry pomysł ?

0

Coś tu jest inaczej. Komunikat mówi, że getAktualny w klasie QuizBean zwraca element typu ArrayList. Tymczasem kod, który wyżej wkleiłeś ma metodę
public ProblemBean getAktualny()
a ProblemBean ma metodę
public ArrayList<Integer> getSekwencja()
która zwraca tą listę. Więc albo dostosuj EL albo metody w klasie, żeby to do siebie pasowało.

0

przepraszam, że dopiero odpisuje.

dopasowałam , tak jak zaproponowałeś. Wyświetla listę :)

import java.io.Serializable;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="quiz")
@SessionScoped
public class QuizBean implements Serializable {

    private ArrayList<ProblemBean> problems = new ArrayList<ProblemBean>();
    private int aktualnyIndeks;
    private int wynik;

    public QuizBean() {
        problems.add(new ProblemBean(new Integer[]{3,1, 4, 1, 5 }, 9));
        problems.add(new ProblemBean(new Integer[]{1,1, 2, 3, 5}, 8));
        problems.add(new ProblemBean(new Integer[]{1,4, 9, 16, 25}, 36));
        problems.add(new ProblemBean(new Integer[]{2, 3, 5, 7, 11}, 13));
        problems.add(new ProblemBean(new Integer[]{1, 2, 4, 8, 16}, 32));

    }

    public void setProblems(ArrayList<ProblemBean> nowaWartosc) {
        problems = nowaWartosc;
        aktualnyIndeks = 0;
        wynik = 0;
    }

    public int getWynik() {
        return wynik;
    }

    public ArrayList<Integer> getAktualny() {
        return problems.get(aktualnyIndeks).getSekwencja();
    }

    public String getOdpowiedz() {
        return "";
    }

    public void setOdpowiedz(String nowaWartosc) {
/* 
        try {
            int odpowiedz = Integer.parseInt(nowaWartosc.trim());
            if (getAktualny().getRozwiazanie() == odpowiedz) {
                wynik++;
            }

            aktualnyIndeks = (aktualnyIndeks + 1) % problems.size();
        } catch (NumberFormatException ex) {
        }
*/
    }
}

Następnie zmodyfikowałam *index.xhml * ze względu na to, że nie pobierał wartości. Obecnie przedstawia się następująco:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title></title>
    </h:head>
    <h:body>
        <h:form>
            <h3>#{msgs.naglowek}</h3>
            <p>
                <h:outputFormat value="#{msgs.aktualnyWynik}">
                    <f:param value="#{quizBean.wynik}"/>
                </h:outputFormat>
            </p>
            <p>#{msgs.zgadnacNext}</p>  


            <h:dataTable id="table1" value="#{quiz.aktualny}" var="item">
                <f:facet name="header">
                    <h:outputText value="Lista liczb w sekwencji" />
                </f:facet>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Liczby" />
                    </f:facet>
                    <h:outputText value="#{item}" />
                </h:column>
            </h:dataTable> 
            <p>#{msgs.odpowiedz}
                <h:inputText value="#{quiz.odpowiedz}"/>
            </p>  
            <p><h:commandButton value="#{msgs.next}"/></p>
        </h:form>
    </h:body>
</html>

Obecnie nie działa mi metodą getRozwiazanie() . jest ona typu *int * chciałabym uprzejmie poprosić o wskazówkę jak pobrać wartość z <h:inputText value="#{quiz.odpowiedz}"/> , a następnie sprawdzić czy poprawna ?

a tak dla bezpieczeństwa. przykład jest na podstawie kodu z książki "JavaServer Faces. Wydanie II". Autorzy: David Geary, Cay S. Horstmann. Rozdział: "Komponenty zarządzane"

0

Obecnie nie działa mi metodą getRozwiazanie() , jest ona typu int Chciałabym uprzejmie poprosić o wskazówkę jak pobrać wartość z

<h:inputText value="#{quiz.odpowiedz}"/> 

, a następnie sprawdzić czy poprawna ?

0

Masz bałagan w tym kodzie straszny: najpierw piszesz #{quizBean.wynik} później #{quiz.odpowiedz}. To chyba trzeba uporządkować. Skoro kod jest z książki, to powinien działać. Masz akomentowaną metodę setOdpowiedz, więc nic się nie będzie działo. To ta metoda pobiera wartość z pola tekstowego formularza. Button nie ma zdefiniowanej akcji, ale nie wiem, czy to jest konieczne, skoro ma wrócić na tą samą stronę.
Nie rozumiem jak może nie działać metoda getRozwiązanie, skoro ona tylko zwraca wartość. Albo inaczej: skąd wiesz, że to ta metoda nie działa? Jakie są komunikaty, jakie błędy albo cokolwiek.
Podsumowując: proponuję poprawić kod, żeby był taki jak w książce a potem napisz konkretnie jakie błędy się pojawiają w działającej aplikacji.

0

Dziękuje serdecznie, że mogę od początku :) :) :) a, wiec tak:

plik index.xhml (z książki ):

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>  
        <title>#{msgs.title}</title>  
    </h:head>
    <h:body>
        <h:form>
            <h3>#{msgs.naglowek}</h3>
            <p>
                <h:outputFormat value="#{msgs.aktualnyWynik}">
                    <f:param value="#{quizBean.wynik}"/>
                </h:outputFormat>
            </p>
            <p>#{msgs.zgadnacNext}</p>  
            <p>#{quizBean.aktualny.sekwencja}</p>  

            <p>#{msgs.odpowiedz}
                <h:inputText value="#{quizBean.odpowiedz}"/>
            </p>  
            <p><h:commandButton value="#{msgs.next}"/></p>
        </h:form>
    </h:body>
</html>

1 błąd
Tu już jest błąd, żle mi wstawia :

Twój wynik null.

a powinien czytać z pliku messages.properties, który przedstawia się w następujący sposób:

title=Quzie liczbowy
naglowek=Miłej zabawy z programem Quiz liczbowy!
aktualnyWynik=Twój wynik {0}.
zgadnacNext=Zgadnij jaka bedzie następna liczba w tej sekwencji!
odpowiedz=Twoja odpowiedz
next=Dalej

wyświetlić powinno : Twój wynik 0.

pobrane z <h:outputFormat value="#{msgs.aktualnyWynik}">

2 błąd
Kolejnym błędem jest , nie wyświetlanie listy

#{quizBean.aktualny.sekwencja}

Zaproponowałeś rozwiązanie :) :) :)</p>
  <h:dataTable id="table1" value="#{quiz.aktualny}" var="item">
                <f:facet name="header">
                    <h:outputText value="Lista liczb w sekwencji" />
                </f:facet>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Liczby" />
                    </f:facet>
                    <h:outputText value="#{item}" />
                </h:column>
            </h:dataTable> 

udało mi się wyświetlić z Twoją pomocą :) :) :)

Klasa ProblemBean (z książki ) odpowiadająca za wyświetlanie listy wartości, przedstawia się :

import java.io.Serializable;
import java.util.ArrayList;

class ProblemBean implements Serializable {
    
    private ArrayList<Integer> sekwencja;
    private int rozwiazanie;
    
    public ProblemBean() {
    }
    
    public ProblemBean(int[] values, int rozwiazanie) {
        sekwencja = new ArrayList<Integer>();
        for (int i = 0; i < values.length; i++) {
            sekwencja.add(values[i]);
        }
        this.rozwiazanie = rozwiazanie;
    }
    
    public ArrayList<Integer> getSekwencja() {

        return sekwencja;
    }
    
    public void setSekwencja(ArrayList<Integer> nowaWartosc) {
        
        sekwencja = nowaWartosc;
    }
    
    public int getRozwiazanie() {
        return rozwiazanie;
    }
    
    public void setRozwiazanie(int nowaWartosc) {
        this.rozwiazanie = nowaWartosc;
    }
}

To może na początku, tą listę wyświetlić za pomocą :

#{quizBean.aktualny.sekwencja}

???

3 błąd
kolejnym błędem jest wprowadzenie wartości polu <h:inputText value="#{quiz.odpowiedz}"/> następnie użycie <h:commandButton value="#{msgs.next}"/> Metodą, która pobiera nowe wczytane dane znajduje się w klasie QuizBean (z książki )

import java.io.Serializable;
import java.util.ArrayList;

public class QuizBean implements Serializable {

    private ArrayList<ProblemBean> problems = new ArrayList<ProblemBean>();
    private int aktualnyIndeks;
    private int wynik;

    public QuizBean() {
        problems.add(new ProblemBean(new int[]{3, 1, 4, 1, 5}, 9));
        problems.add(new ProblemBean(new int[]{1, 1, 2, 3, 5}, 8));
        problems.add(new ProblemBean(new int[]{1, 4, 9, 16, 25}, 36));
        problems.add(new ProblemBean(new int[]{2, 3, 5, 7, 11}, 13));
        problems.add(new ProblemBean(new int[]{1, 2, 4, 8, 16}, 32));

    }

    public void setProblems(ArrayList<ProblemBean> nowaWartosc) {
        problems = nowaWartosc;
        aktualnyIndeks = 0;
        wynik = 0;
    }

    public int getWynik() {
        return wynik;
    }

    public ProblemBean getAktualny() {
        return problems.get(aktualnyIndeks);
    }

    public String getOdpowiedz() {
        return "";
    }

    public void  setOdpowiedz(String nowaWartosc) {

        try {
            int odpowiedz = Integer.parseInt(nowaWartosc.trim());
            if (getAktualny().getRozwiazanie() == odpowiedz) {
                wynik++;
            }

            aktualnyIndeks = (aktualnyIndeks + 1) % problems.size();
        } catch (NumberFormatException ex) {
        }

    }
}

po wprowadzeniu , wartości pojawia się następujący komunikat :

javax.el.PropertyNotFoundException: /index.xhtml @21,61 value="#{quizBean.odpowiedz}": Target Unreachable, identifier 'quizBean' resolved to null
[...]

Może na początku od wyświetlenia listy ...

  <p>#{quizBean.aktualny.sekwencja}</p>  

Zawszę mam z tymi listami jakieś problemy , ehhh

0

:) :) :)
Udało mi się naprawić błędy powyższe :) :) :)

Nie określiłam dostępu *public * do klasy *ProblemBean * , trochę się pogubiłam. Myślałam, że jak się nie napisze public to klasa właśnie taki dostęp będzie miała określony...?

Mam jeszcze jedno pytanko , gdy użytkownik wprowadzi dla wyświetlonych liczb:
[3, 1, 4, 1, 5] , cyfrę: 9. To wynik zostanie prawidłowo wyświetlony:
Twój wynik 1.

W tym momencie wyświetla się kolejny przykład:
[1, 1, 2, 3, 5] użytkownik wprowadzi cyfrę: 8 To wynik już, źle wyświetla:
Twój wynik 0.

Nie wiem czemu zmienna *wynik * nie jest inkrementowana poprawnie? W sumie prawie nic się nie zmieniło w kodzie , klasa ProblemBean przedstawia się w ten sposób:

import java.io.Serializable;
import java.util.ArrayList;

public class ProblemBean implements Serializable {
 
    private ArrayList<Integer> sekwencja;
    private int rozwiazanie;
 
    public ProblemBean() {
    }
 
    public ProblemBean(int[] values, int rozwiazanie) {
        sekwencja = new ArrayList<Integer>();
        for (int i = 0; i < values.length; i++) {
            sekwencja.add(values[i]);
        }
        this.rozwiazanie = rozwiazanie;
    }
 
    public ArrayList<Integer> getSekwencja() {
        return sekwencja;
    }
 
    public void setSekwencja(ArrayList<Integer> nowaWartosc) {
        sekwencja = nowaWartosc;
    }
 
    public int getRozwiazanie() {
        return rozwiazanie;
    }
 
    public void setRozwiazanie(int nowaWartosc) {
        this.rozwiazanie = nowaWartosc;
    }
}

Klasa QuizBean :

import java.io.Serializable;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;

@ManagedBean(name="quiz") 

public class QuizBean implements Serializable {

    private ArrayList<ProblemBean> problems = new ArrayList<ProblemBean>();
    private int aktualnyIndeks;
    private int wynik;

    public QuizBean() {
        problems.add(new ProblemBean(new int[]{3, 1, 4, 1, 5}, 9));
        problems.add(new ProblemBean(new int[]{1, 1, 2, 3, 5}, 8));
        problems.add(new ProblemBean(new int[]{1, 4, 9, 16, 25}, 36));
        problems.add(new ProblemBean(new int[]{2, 3, 5, 7, 11}, 13));
        problems.add(new ProblemBean(new int[]{1, 2, 4, 8, 16}, 32));

    }

    public void setProblems(ArrayList<ProblemBean> nowaWartosc) {
        problems = nowaWartosc;
        aktualnyIndeks = 0;
        wynik = 0;
    }

    public int getWynik() {
        return wynik;
    }

    public ProblemBean getAktualny() {
        return problems.get(aktualnyIndeks);
    }

    public String getOdpowiedz() {
        return "";
    }

    public void  setOdpowiedz(String nowaWartosc) {

        try {
            int odpowiedz = Integer.parseInt(nowaWartosc.trim());
            if (getAktualny().getRozwiazanie() == odpowiedz) {
                wynik++;
            }

            aktualnyIndeks = (aktualnyIndeks + 1) % problems.size();
        } catch (NumberFormatException ex) {
        }

    }
}

Wyświetlanie wyników na stronie index.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>  
        <title>#{msgs.title}</title>  
    </h:head>
    <h:body>
        <h:form>
            <h3>#{msgs.naglowek}</h3>
            <p>
                <h:outputFormat value="#{msgs.aktualnyWynik}">
                    <f:param value="#{quiz.wynik}"/>
                </h:outputFormat>
            </p>
            <p>#{msgs.zgadnacNext}</p>
            <h3> #{quiz.aktualny.sekwencja}</h3>
          

            <p>#{msgs.odpowiedz}</p>
            <h:inputText value="#{quiz.odpowiedz}"/>

            <p><h:commandButton value="#{msgs.next}"/></p>
        </h:form>
    </h:body>
</html>

plik konfiguracyjny facs-confing.xml:

<faces-config version="2.0"  
    xmlns="http://java.sun.com/xml/ns/javaee"   
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">  
      
    <application>     
        <locale-config>
            <default-locale>pl</default-locale>
            <supported-locale>de</supported-locale>
        </locale-config>
        <resource-bundle>
            <base-name>com.corejsf.messages</base-name>
            <var>msgs</var>
        </resource-bundle>        
    </application>
</faces-config>

Ustawienie wartości zastępczych dla messages.properties :

title=Quzie liczbowy
naglowek=Miłej zabawy z programem Quiz liczbowy!
aktualnyWynik=Twój wynik {0}.
zgadnacNext=Zgadnij jaka bedzie następna liczba w tej sekwencji!
odpowiedz=Twoja odpowiedz
next=Dalej

Nie rozumiem, czemu poniższy znacznik uzyskany z komponentu msgs.aktualnyWynik nie jest uaktualniany ..?

<h:outputFormat value="#{msgs.aktualnyWynik}">
        <f:param value="#{quiz.wynik}"/>
</h:outputFormat>

Prosiłabym uprzejmie o jakąś wskazówkę ...?

2

Cieszę się, że ci się udało rozwiązać poprzednie problemy :)
Co do tej kwestii: zwróć uwagę na coś takiego, jak zasięg komponentów. Książka, którą masz jest o JSF 1.2, ale piszesz już z adnotacjami z 2.0, więc powinno być łatwo to zrobić. Problem wynika z tego, że ta wartość zapamiętuje się w komponencie, który jest tworzony na nowo po przeładowaniu strony, a co za tym idzie jako nowy nie ma zapisanej wartości ze starego. Wystarczy nadać mu zasięg sesji i wtedy powinno się to zapamiętać. Istnieją też inne zasięgi, ale to sobie poczytasz już.

1

DZIĘKUJE DZIAŁA :) :) :)

dodałam w klasie QuizBean poniższą adnotację:

@SessionScoped

należącą do pakietu:

javax.faces.bean.SessionScoped;

:) :) :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1