2010-05-06 9 views
10

Ho un databale su index.xhtmlCome ottenere l'indice di riga selezionato in JSF datatable?

<h:dataTable style="border: solid 2px black;" 
    value="#{IndexBean.bookList}" var="item" 
    binding="#{IndexBean.datatableBooks}"> 

    <h:column> 
     <h:commandButton value="Edit" actionListener="#{IndexBean.editBook}"> 
      <f:param name="index" value="#{IndexBean.datatableBooks.rowIndex}"/> 
     </h:commandButton> 
    </h:column> 
</h:dataTable> 

mio fagiolo:

@ManagedBean(name="IndexBean") 
@ViewScoped 
public class IndexBean implements Serializable { 
    private HtmlDataTable datatableBooks; 

    public HtmlDataTable getDatatableBooks() { 
     return datatableBooks; 
    } 

    public void setDatatableBooks(HtmlDataTable datatableBooks) { 
     this.datatableBooks = datatableBooks; 
    } 

    public void editBook() throws IOException{ 
     int index = Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("index").toString()); 
     System.out.println(index); 
    } 
} 

mio problema è che ho sempre lo stesso indice nel registro del server anche se clicco i diversi tasti di modifica. Immagina che ci sia una raccolta che viene fornita al datatable. Non l'ho mostrato in fagiolo.

Se cambio ambito da ViewScope a RequestScope, funziona correttamente. Quale può essere il problema con @ViewScoped? Grazie in anticipo :)

EDIT:

<h:column> 
    <h:commandButton value="Edit" actionListener="#{IndexBean.editBook}" /> 
</h:column> 

public void editBook(ActionEvent ev) throws IOException{ 
    if (ev.getSource() != null && ev.getSource() instanceof HtmlDataTable) { 
     HtmlDataTable objHtmlDataTable = (HtmlDataTable) ev.getSource(); 
     System.out.println(objHtmlDataTable.getRowIndex()); 
    } 
} 
+0

correlati: http://stackoverflow.com/questions/4994458/how-can-i -pass-a-un-parametro-a-un-commandlink-inside-a-datatable – BalusC

risposta

14

Hai già associato il componente <h:dataTable> al bean. Tutto quello che dovete fare è:

public void editBook() throws IOException{ 
    int index = datatableBooks.getRowIndex(); // Actually not interesting info. 
    Book book = (Book) datatableBooks.getRowData(); // This is what you want. 
} 

Il <f:param> non è anche necessario qui. Per ulteriori suggerimenti, vedere anche this article.

Aggiornamento: Posso riprodurre il problema. Questo è probabilmente un bug con @ViewScoped. Quando il bean è impostato su @RequestScoped, funziona come previsto. Anche quando si rimuove il collegamento del componente e si ottiene il componente dal viewroot stesso, funziona come previsto. Ho registrato issue 1658 su questo.

+1

Ciao BalusC, il tuo articolo è ottimo come al solito :). La tua risposta funziona se il mio bean è @RequestScoped. Ma la mia vera domanda rimane comunque, perché non funziona in @ViewScoped? Se cambio l'annotazione da @RequestScoped a @ViewScoped, ottengo sempre la risposta che ho ricevuto la prima volta. Ho bisogno che il mio bean sia @ViewScoped. Che soluzione alternativa posso eventualmente fare? – TCM

+0

Dove carichi 'bookList'? – BalusC

+0

Lo carico nel callback @PostConstruct. Sto facendo qualcosa di sbagliato? Dove dovrei caricare? – TCM

1

Che cosa si può fare è quello di utilizzare il metodo [getRowData()][1] sul bean Java per ottenere direttamente l'oggetto situato sulla linea che ospita il pulsante su cui l'utente ha fatto clic.

Un esempio di codice:

public void editBook(ActionEvent evt) { 
    // We get the table object 
    HtmlDataTable table = getParentDatatable((UIComponent) evt.getSource()); 
    // We get the object on the selected line. 
    Object o = table.getRowData(); 
    // Eventually, if you need the index of the line, simply do: 
    int index = table.getRowIndex(); 
    // ... 
} 

// Method to get the HtmlDataTable. 
private HtmlDataTable getParentDatatable(UIComponent compo) { 
    if (compo == null) { 
     return null; 
    } 
    if (compo instanceof HtmlDataTable) { 
     return (HtmlDataTable) compo; 
    } 
    return getParentDataTable(compo.getParent()); 
} 


Modifica

Il codice JSF ora assomiglia:

<h:commandButton value="Edit" actionListener="#{IndexBean.editBook}"/> 

Inoltre, non dimenticare di cambiare la firma di Metodo editBook(), impostando un argomento javax.faces.event.ActionEvent.

+0

Ciao romaintaz, ma ho provato la tua soluzione e non sembra funzionare. Continuo a ricevere le eccezioni "SEVERE: Ricevuto 'javax.el.MethodNotFoundException' quando si richiama il listener di azioni '# {IndexBean.editBook}' per il componente 'j_idt35' SEVERE: javax.el.MethodNotFoundException: Metodo non trovato: IndexBean @ d15176.editBook() " Please help :( – TCM

+0

Vedere la mia modifica, può risolvere il tuo problema – romaintaz

+0

Ciao, per favore leggi la mia modifica Ho fatto esattamente quello che hai detto e ottengo ancora l'eccezione MethodNotFoundException. Non ho capito cosa intendevi per "Inoltre, non modificare per cambiare la firma del metodo editBook(), impostando un argomento javax.faces.event.ActionEvent." Non ho definito nulla in faces-config.xml. Non appena passo AzioneAvvia si inizia a dire MethodNotFoundException – TCM

0

Se si utilizza EL 2.2, ad esempio con Tomcat7 si può provare

<h:commandLink action="#{IndexBean.editBook(item)}" immediate="true"> 

spero di aiutare

Problemi correlati