如何在dataTable中将选定的行传递给commandLink? [英] How can I pass selected row to commandLink inside dataTable?
问题描述
< 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 =idvalue =#{item.id}/>
< / p:commandLink>
< / p:column>
< / p:dataTable>
但它总是产生0 - 显然是行变量 f
在渲染属性时不可用(在使用固定值时它可以工作)
任何人都有替代解决方案?
关于原因,< f:attribute>
特定于组件本身
有几种方法可以实现需求。
-
使用
< f:param>
。它添加一个请求参数。< h:commandLink action =#{bean.insert}value =insert >
< f:param name =idvalue =#{item.id}/>
< / h:commandLink>
如果你的bean是请求作用域,让JSF通过
@ManagedProperty
@ManagedProperty(value =#{param.id})
private Long id; // + setter
或者如果您的bean有更广泛的范围,或者如果您想要更细粒度的验证/转换,请使用
< f:viewParam>
,另请参阅 f:viewParam vs @ManagedProperty :< f:viewParam name =idvalue = #{bean.id}required =true/>
无论哪种方式,这样做的优点是数据模型不一定需要保留在表单中提交(对于您的bean是请求范围的情况)。
-
使用
< 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
in action方法。这仅需要为表单提交请求保留数据模型。最好是将bean放在视图范围内,由@ViewScoped
。
-
如果您的servlet容器支持Servlet 3.0 / EL 2.2,那么只需将其作为method参数传递。这也要求为表单提交请求保留数据模型。最好是将bean放在视图范围内,由
@ViewScoped
。< h:commandLink action =#{bean.insert(item.id)}value =insert/>
结合:
public void insert(Long id){
// ...
}
您甚至可以传递整个项目对象:
< h:commandLink action =# {bean.insert(item)}value =insert/>
with:
code> public void insert(Item item){
// ...
}
在Servlet 2.5容器上,如果您提供支持此功能的EL实现,也可以像JBoss EL一样。有关配置详细信息,请参阅此答案。
-
将datatable值绑定到
DataModel< E>
,而这又反过来包裹项目。< h:dataTable value =#{bean.model}var =item>
与
private transient DataModel< Item>模型;
public DataModel< Item> getModel(){
if(model == null){
model = new ListDataModel< Item>(items);
}
返回模型;
}
(使其
transient
并且在getter中实例化它是强制性的,因为DataModel
不实现可序列化
)
然后你可以通过
DataModel#getRowData()
,而不传递任何东西(JSF根据点击的命令链接/按钮的请求参数名称确定行)。public void insert(){
Item item = model.getRowData();
Long id = item.getId();
// ...
}
这也要求数据模型是保存为表单提交请求。最好是将bean放在视图范围内,由
@ViewScoped
。
-
您可以使用
应用程序#evaluateExpressionGet()
以编程方式评估当前的#{item}
。public void insert(){
FacesContext context = FacesContext.getCurrentInstance();
项目项目= context.getApplication()。evaluateExpressionGet(context,#{item},Item.class);
Long id = item.getId();
// ...
}
选择哪种方式取决于功能需求,以及其他功能是否为其他目的提供了更多优势。我个人将继续使用#3,或者当您还要支持servlet 2.5容器时,#2。
I'm using Primefaces in a JSF 2 application. I have a <p:dataTable>
, and instead of selecting rows, I want the user to be able to directly execute various actions on individual rows. For that, I have several <p:commandLink>
s in the last column.
My problem: how can I pass a row ID to the action started by the command link so that I know which row to act on? I tried using an <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>
But it always yields 0 - apparently the row variable f
is not available when the attribute is rendered (it works when I use a fixed value).
Anyone has an alternative solution?
As to the cause, the <f:attribute>
is specific to the component itself (populated during view build time), not to the iterated row (populated during view render time).
There are several ways to achieve the requirement.
Use
<f:param>
instead. It adds a request parameter.<h:commandLink action="#{bean.insert}" value="insert"> <f:param name="id" value="#{item.id}" /> </h:commandLink>
If your bean is request scoped, let JSF set it by
@ManagedProperty
@ManagedProperty(value="#{param.id}") private Long id; // +setter
Or if your bean has a broader scope or if you want more fine grained validation/conversion, use
<f:viewParam>
on the target view, see also f:viewParam vs @ManagedProperty:<f:viewParam name="id" value="#{bean.id}" required="true" />
Either way, this has the advantage that the datamodel doesn't necessarily need to be preserved for the form submit (for the case that your bean is request scoped).
Use
<f:setPropertyActionListener>
instead. The advantage is that this removes the need for accessing the request parameter map when the bean has a broader scope than the request scope.<h:commandLink action="#{bean.insert}" value="insert"> <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" /> </h:commandLink>
In combination with
private Long id; // +setter
It'll be just available by property
id
in action method. This only requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by@ViewScoped
.If your servletcontainer supports Servlet 3.0 / EL 2.2, then just pass it as method argument. This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by
@ViewScoped
.<h:commandLink action="#{bean.insert(item.id)}" value="insert" />
In combination with:
public void insert(Long id) { // ... }
You can even pass the entire item object:
<h:commandLink action="#{bean.insert(item)}" value="insert" />
with:
public void insert(Item item) { // ... }
On Servlet 2.5 containers, this is also possible if you supply an EL implementation which supports this, like as JBoss EL. For configuration detail, see this answer.
Bind the datatable value to
DataModel<E>
instead which in turn wraps the items.<h:dataTable value="#{bean.model}" var="item">
with
private transient DataModel<Item> model; public DataModel<Item> getModel() { if (model == null) { model = new ListDataModel<Item>(items); } return model; }
(making it
transient
and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean sinceDataModel
doesn't implementSerializable
)Then you'll be able to access the current row by
DataModel#getRowData()
without passing anything around (JSF determines the row based on the request parameter name of the clicked command link/button).public void insert() { Item item = model.getRowData(); Long id = item.getId(); // ... }
This also requires that the datamodel is preserved for the form submit request. Best is to put the bean in the view scope by
@ViewScoped
.You can use
Application#evaluateExpressionGet()
to programmatically evaluate the current#{item}
.public void insert() { FacesContext context = FacesContext.getCurrentInstance(); Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class); Long id = item.getId(); // ... }
Which way to choose depends on the functional requirements and whether the one or the other offers more advantages for other purposes. I personally would go ahead with #3 or, when you'd like to support servlet 2.5 containers as well, with #2.
这篇关于如何在dataTable中将选定的行传递给commandLink?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!