2010-05-06 19 views
10

Tengo un databale en index.xhtml¿Cómo obtener el índice de fila seleccionado en la tabla de datos JSF?

<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> 

Mi frijol:

@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); 
    } 
} 

Mi problema es que siempre me sale el mismo índice en el registro del servidor a pesar de que haga clic en los diferentes botones de edición. Imagine que hay una colección que se suministra a la tabla de datos. No lo he demostrado en Bean.

Si cambio el ámbito de ViewScope a RequestScope, funciona bien. ¿Cuál puede ser el problema con @ViewScoped? Gracias de antemano :)

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

relacionadas: http://stackoverflow.com/questions/4994458/how-can-i -pass-a-parameter-to-a-commandlink-inside-a-datatable – BalusC

Respuesta

14

Ya ha vinculado el componente <h:dataTable> al bean. Todo lo que necesita hacer es:

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

El <f:param> tampoco es para continuar. Para obtener más consejos, también vea this article.

Actualización: Puedo reproducir su problema. Es probable que se trate de un error con @ViewScoped. Cuando el bean se establece en @RequestScoped, funciona como se esperaba. Además, cuando elimina el enlace del componente y obtiene el componente desde viewroot usted mismo, funciona como se esperaba. He archivado issue 1658 sobre esto.

+1

Hola BalusC, tu artículo es genial como de costumbre :). Su respuesta funciona si mi bean es @RequestScoped. Pero mi verdadera pregunta sigue siendo, ¿por qué no funciona en @ViewScoped? Si solo cambio la anotación de @RequestScoped a @ViewScoped, siempre obtengo la respuesta que recibí la primera vez. Necesito que mi bean sea @ViewScoped. ¿Qué solución puedo hacer? – TCM

+0

¿Dónde se carga 'bookList'? – BalusC

+0

Lo cargo en la devolución de llamada @PostConstruct. ¿Estoy haciendo algo mal? ¿Dónde debo cargar? – TCM

1

Lo que puede hacer es utilizar el método [getRowData()][1] en el bean Java para obtener directamente el objeto situado en la línea que aloja el botón en el que el usuario hizo clic.

Un ejemplo de código:

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()); 
} 


Edición

El código JSF ahora se ve así:

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

Además, no se olvide de cambiar la firma de editBook() método, estableciendo un argumento javax.faces.event.ActionEvent.

+0

Hola romaintaz, pero probé tu solución y parece que no funciona. Sigo recibiendo excepciones "SEVERE: Recibí 'javax.el.MethodNotFoundException' al invocar el detector de acciones '# {IndexBean.editBook}' para el componente 'j_idt35' SEVERE: javax.el.MethodNotFoundException: Método no encontrado: IndexBean @ d15176.editBook() " Por favor ayuda :( – TCM

+0

Ver mi edición, puede resolver su problema – romaintaz

+0

Hola, por favor lea mi edición. Hice exactamente lo que dijo y todavía tengo la excepción MethodNotFoundException. No entendí lo que quería decir con "Además, no modifiques para cambiar la firma del método editBook() estableciendo un argumento javax.faces.event.ActionEvent." No tengo nada definido en faces-config.xml. Tan pronto como paso ActionEvent comienza diciendo MethodNotFoundException – TCM

0

Si utiliza EL 2.2, por ejemplo, con Tomcat7 puede probar

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

espero ayudar

Cuestiones relacionadas