如何将选定的行传递给dataTable或ui中的commandLink:repeat?

我在JSF 2应用程序中使用Primefaces。 我有一个<p:dataTable> ,而不是select行,我希望用户能够直接执行各行的各种行动。 为此,我在最后一列有几个<p:commandLink>

我的问题是:如何将行ID传递给由命令链接启动的操作,以便我知道哪一行要执行? 我尝试使用<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> 

但它总是会产生0 – 显然行属性f是不可用当属性被渲染(它使用固定值时)。

任何人都有其他解决scheme?

至于原因, <f:attribute>是特定于组件本身的(在视图构build时填充的),而不是迭代的行(在视图渲染时填充)。

有几种方法可以达到这个要求。

  1. 改为使用<f:param> 。 它添加了一个请求参数。

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

    如果你的bean被请求作用域,让JSF通过@ManagedProperty设置它

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

    或者,如果你的bean有更广泛的范围,或者你想要更精细的validation/转换,请在目标视图中使用<f:viewParam> ,另请参阅f:viewParam vs @ManagedProperty :

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

    无论哪种方式,这有一个好处,即数据模型不一定需要被保留用于表单提交(对于你的bean被请求作用域的情况)。


  2. 改为使用<f:setPropertyActionListener> 。 优点是当bean的范围比请求范围更广时,这就消除了访问请求参数映射的需要。

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

    与…结合

     private Long id; // +setter 

    这只能通过操作方法中的属性id来获得。 这只需要为表单提交请求保留数据模型。 最好的方法是将bean放在@ViewScoped的视图范围中。


  3. 如果您的servletcontainer支持Servlet 3.0 / EL 2.2,那么只需将其作为方法parameter passing即可。 这也要求为表单提交请求保留数据模型。 最好的方法是将bean放在@ViewScoped的视图范围中。

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

    结合:

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

    你甚至可以传递整个项目对象:

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

    有:

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

    在Servlet 2.5容器上,如果你提供一个支持这个的EL实现,就像JBoss EL一样,这也是可能的。 有关configuration详细信息,请参阅此答案 。


  4. 将数据表值绑定到DataModel<E>而不是包装项目。

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

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

    (因为DataModel没有实现Serializable所以当你在一个视图或会话范围的bean上使用它的时候,使得它在getter中是transient并且懒洋洋地实例化它是强制性的)

    然后,您将能够通过DataModel#getRowData()访问当前行而不传递任何东西(JSF根据单击的命令链接/button的请求参数名称确定行)。

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

    这也要求为表单提交请求保留数据模型。 最好的方法是将bean放在@ViewScoped的视图范围中。


  5. 您可以使用Application#evaluateExpressionGet()以编程方式评估当前的#{item}

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

select哪种方式取决于function要求,以及是否为其他目的提供更多优势。 我个人会继续使用#3,或者当您想要支持servlet 2.5容器时,使用#2。

在JSF 1.2中,这是通过<f:setPropertyActionListener> (在命令组件内)完成的。 在JSF 2.0(精确到EL 2.2,感谢BalusC)可以这样做: action="${filterList.insert(f.id)}

在我的观点页面:

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

支持豆

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

感谢Mkyong这个网站 , 实际为我们传递参数的唯一解决scheme就是这个

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

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

从技术上讲,您不能直接传递给方法本身,而是传递给JSF request parameter map

Interesting Posts