seleccionar rowselect obtener index fila ejemplo datos jsf jsf-2 datatable parameter-passing commandlink

jsf - obtener - rowselect primefaces



¿Cómo puedo pasar la fila seleccionada a commandLink dentro de dataTable o ui: repeat? (4)

Estoy usando Primefaces en una aplicación JSF 2. Tengo un <p:dataTable> , y en lugar de seleccionar filas, quiero que el usuario pueda ejecutar directamente varias acciones en filas individuales. Para eso, tengo varios <p:commandLink> s en la última columna.

Mi problema: ¿cómo puedo pasar una identificación de fila a la acción iniciada por el enlace de comando para saber en qué fila actuar? Intenté usar un <f:attribute> :

<p:dataTable value="#{bean.items}" var="item"> ... <p:column> <p:commandLink actionListener="#{bean.insert}" value="insert"> <f:attribute name="id" value="#{item.id}" /> </p:commandLink> </p:column> </p:dataTable>

Pero siempre produce 0, aparentemente la variable de fila f no está disponible cuando se representa el atributo (funciona cuando uso un valor fijo).

Alguien tiene una solución alternativa?


En JSF 1.2 esto fue hecho por <f:setPropertyActionListener> (dentro del componente de comando). En JSF 2.0 (EL 2.2 para ser precisos, gracias a BalusC) es posible hacerlo así: action="${filterList.insert(f.id)}


En cuanto a la causa, el <f:attribute> es específico del componente en sí (poblado durante el tiempo de compilación de la vista), no de la fila iterada (poblado durante el tiempo de visualización de la vista).

Hay varias formas de lograr el requisito.

  1. Use <f:param> lugar. Agrega un parámetro de solicitud.

    <h:commandLink action="#{bean.insert}" value="insert"> <f:param name="id" value="#{item.id}" /> </h:commandLink>

    Si su bean tiene un alcance de solicitud, deje que JSF lo configure por @ManagedProperty

    @ManagedProperty(value="#{param.id}") private Long id; // +setter

    O si su bean tiene un alcance más amplio o si desea una validación / conversión más detallada, use <f:viewParam> en la vista de destino, vea también f: viewParam vs @ManagedProperty :

    <f:viewParam name="id" value="#{bean.id}" required="true" />

    De cualquier forma, esto tiene la ventaja de que el modelo de datos no necesariamente se debe conservar para el envío del formulario (en el caso de que su bean tenga un alcance de solicitud).

  2. Use <f:setPropertyActionListener> lugar. La ventaja es que esto elimina la necesidad de acceder al mapa de parámetros de solicitud cuando el bean tiene un alcance más amplio que el alcance de la solicitud.

    <h:commandLink action="#{bean.insert}" value="insert"> <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" /> </h:commandLink>

    En combinación con

    private Long id; // +setter

    Estará disponible solo por id propiedad en el método de acción. Esto solo requiere que el modelo de datos se preserve para la solicitud de envío de formularios. Lo mejor es poner el bean en el alcance de la vista mediante @ViewScoped .

  3. Si su servletcontainer admite Servlet 3.0 / EL 2.2, simplemente páselo como argumento de método. Esto también requiere que el modelo de datos se preserve para la solicitud de envío de formularios. Lo mejor es poner el bean en el alcance de la vista mediante @ViewScoped .

    <h:commandLink action="#{bean.insert(item.id)}" value="insert" />

    En combinación con:

    public void insert(Long id) { // ... }

    Incluso puede pasar todo el objeto del elemento:

    <h:commandLink action="#{bean.insert(item)}" value="insert" />

    con:

    public void insert(Item item) { // ... }

    En los contenedores Servlet 2.5, esto también es posible si proporciona una implementación EL que lo soporte, como JBoss EL. Para detalles de configuración, vea esta respuesta .

  4. Enlace el valor de DataModel<E> de DataModel<E> a DataModel<E> en su lugar, que a su vez envuelve los elementos.

    <h:dataTable value="#{bean.model}" var="item">

    con

    private transient DataModel<Item> model; public DataModel<Item> getModel() { if (model == null) { model = new ListDataModel<Item>(items); } return model; }

    (Hacerlo transient y crear instancias perezosamente en el getter es obligatorio cuando se usa esto en una vista o en un bean con ámbito de sesión dado que DataModel no implementa Serializable )

    A continuación, podrá acceder a la fila actual por DataModel#getRowData() sin pasar nada (JSF determina la fila en función del nombre del parámetro de solicitud del enlace / botón de comando al que se hace clic).

    public void insert() { Item item = model.getRowData(); Long id = item.getId(); // ... }

    Esto también requiere que el modelo de datos se preserve para la solicitud de envío de formularios. Lo mejor es poner el bean en el alcance de la vista mediante @ViewScoped .

  5. Puede usar Application#evaluateExpressionGet() para evaluar programáticamente el #{item} actual.

    public void insert() { FacesContext context = FacesContext.getCurrentInstance(); Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class); Long id = item.getId(); // ... }

La forma de elegir depende de los requisitos funcionales y de si uno u otro ofrece más ventajas para otros fines. Personalmente, seguiría con el n. ° 3 o, cuando también quisiera admitir contenedores Servlet 2.5, con el n. ° 2.


En mi página de vista:

<p:dataTable ...> <p:column> <p:commandLink actionListener="#{inquirySOController.viewDetail}" process="@this" update=":mainform:dialog_content" oncomplete="dlg2.show()"> <h:graphicImage library="images" name="view.png"/> <f:param name="trxNo" value="#{item.map[''trxNo'']}"/> </p:commandLink> </p:column> </p:dataTable>

respaldo de frijol

public void viewDetail(ActionEvent e) { String trxNo = getFacesContext().getRequestParameterMap().get("trxNo"); for (DTO item : list) { if (item.get("trxNo").toString().equals(trxNo)) { System.out.println(trxNo); setSelectedItem(item); break; } } }


Gracias a este sitio de Mkyong , la única solución que realmente funcionó para que pasáramos un parámetro fue este

<h:commandLink action="#{user.editAction}"> <f:param name="myId" value="#{param.id}" /> </h:commandLink>

con

public String editAction() { Map<String,String> params = FacesContext.getExternalContext().getRequestParameterMap(); String idString = params.get("myId"); long id = Long.parseLong(idString); ... }

Técnicamente, no se puede pasar directamente al método, sino al JSF request parameter map .