提问人:Michael Borgwardt 提问时间:2/15/2011 最后编辑:BalusCMichael Borgwardt 更新时间:8/11/2020 访问量:177774
如何将选中的行传递给dataTable或ui:repeat中的commandLink?
How can I pass selected row to commandLink inside dataTable or ui:repeat?
问:
我在 JSF 2 应用程序中使用 Primefaces。我有一个 ,而不是选择行,我希望用户能够直接对单个行执行各种操作。为此,我在最后一列中有几个 s。<p:dataTable>
<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
有人有替代解决方案吗?
答:
在 JSF 1.2 中,这是由(在命令组件中)完成的。在 JSF 2.0 中(准确地说是 EL 2.2,感谢 BalusC),可以这样做:<f:setPropertyActionListener>
action="${filterList.insert(f.id)}
评论
至于原因,特定于组件本身(在视图构建时填充),而不是迭代行(在视图渲染时填充)。<f:attribute>
有几种方法可以满足这一要求。
如果您的 servletcontainer 至少支持 Servlet 3.0 / EL 2.2,那么只需将其作为组件或标签的 action/listener 方法的参数传递即可。例如
UICommand
AjaxBehavior
<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
结合:
public void insert(Long id) { // ... }
这只需要为表单提交请求保留数据模型。最好是将 Bean 放在视图范围内。
@ViewScoped
您甚至可以传递整个 item 对象:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
跟:
public void insert(Item item) { // ... }
在 Servlet 2.5 容器上,如果您提供支持此的 EL 实现,例如 JBoss EL,这也是可能的。有关配置详细信息,请参阅此答案。
在组件中使用
<f:param>
。它添加一个请求参数。UICommand
<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 具有更广泛的范围,或者如果您想要更细粒度的验证/转换,请在目标视图上使用 <f:
viewParam>
,另请参阅 f:viewParam 与 @ManagedProperty:<f:viewParam name="id" value="#{bean.id}" required="true" />
无论哪种方式,这样做的优点是,不一定需要为表单提交保留数据模型(对于您的 Bean 是请求范围的)。
在组件中使用
<f:setPropertyActionListener>
。优点是,当 Bean 的范围比请求范围更广时,无需访问请求参数映射。UICommand
<h:commandLink action="#{bean.insert}" value="insert"> <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" /> </h:commandLink>
结合
private Long id; // +setter
它只能通过属性操作方法获得。这只需要为表单提交请求保留数据模型。最好是将 Bean 放在视图范围内。
id
@ViewScoped
而是将 datatable 值绑定到
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; }
(当您在视图或会话范围的 Bean 上使用它时,必须将其设置为
瞬态
并在 getter 中延迟实例化它,因为DataModel
未实现Serializable
)然后,您将能够通过
DataModel#getRowData()
访问当前行,而无需传递任何内容(JSF 根据单击的命令链接/按钮的请求参数名称确定行)。public void insert() { Item item = model.getRowData(); Long id = item.getId(); // ... }
这还需要为表单提交请求保留数据模型。最好是将 Bean 放在视图范围内。
@ViewScoped
使用
Application#evaluateExpressionGet()
以编程方式计算当前的 .#{item}
public void insert() { FacesContext context = FacesContext.getCurrentInstance(); Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class); Long id = item.getId(); // ... }
选择哪种方式取决于功能要求,以及其中一种或另一种是否为其他目的提供更多优势。我个人会继续使用 #1,或者,当您也想支持 servlet 2.5 容器时,请使用 #2。
评论
在我的视图页面中:
<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 的这个网站,唯一真正适合我们传递参数的解决方案是这个
<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
评论
#{param}
评论