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

Estoy usando Primefaces en una aplicación JSF 2. Tengo un

, y en lugar de seleccionar filas, quiero que el usuario pueda ejecutar directamente varias acciones en filas individuales. Para eso, tengo varios

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 :

 

...

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 cuanto a la causa, el es específico del componente en sí (poblado durante el tiempo de comstackció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 lugar. Agrega un parámetro de solicitud.

        

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

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

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

      

    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 scope de solicitud).


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

        

    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 scope 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 scope de la vista mediante @ViewScoped .

      

    En combinación con:

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

    Incluso puede pasar todo el objeto del elemento:

      

    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 de DataModel a DataModel en su lugar, que a su vez envuelve los elementos.

      

    con

     private transient DataModel model; public DataModel getModel() { if (model == null) { model = new ListDataModel(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 scope 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 JSF 1.2 esto fue hecho por (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 mi página de vista:

         

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

    

con

 public String editAction() { Map 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 .