如何将选定的行传递给 dataTable 或 ui:repeat 中的 commandLink? [英] How can I pass selected row to commandLink inside dataTable or ui:repeat?

查看:15
本文介绍了如何将选定的行传递给 dataTable 或 ui:repeat 中的 commandLink?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 JSF 2 应用程序中使用 Primefaces.我有一个 <p:dataTable>,我希望用户能够直接对各个行执行各种操作,而不是选择行.为此,我在最后一列中有几个 .

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.

我的问题:如何将行 ID 传递给由命令链接启动的操作,以便我知道要对哪一行执行操作?我尝试使用 :

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>

但它总是产生 0 - 显然当属性呈现时行变量 f 不可用(当我使用固定值时它有效).

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.

  1. 如果您的 servletcontainer 至少支持 Servlet 3.0/EL 2.2,那么只需将其作为 UICommand 组件或 AjaxBehavior 的 action/listener 方法的参数传递标签.例如

  1. If your servletcontainer supports a minimum of Servlet 3.0 / EL 2.2, then just pass it as an argument of action/listener method of UICommand component or AjaxBehavior tag. E.g.

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

结合:

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

这只需要为表单提交请求保留数据模型.最好是通过 @ViewScoped 将 bean 放入视图范围.

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.

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

You can even pass the entire item object:

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

与:

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

在 Servlet 2.5 容器上,如果您提供支持此功能的 EL 实现(如 JBoss EL),这也是可能的.有关配置详细信息,请参阅此答案.

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.

使用UICommand 组件中.它添加了一个请求参数.

Use <f:param> in UICommand component. It adds a request parameter.

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

如果你的 bean 是请求范围的,让 JSF 通过 @ManagedProperty

If your bean is request scoped, let JSF set it by @ManagedProperty

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

或者,如果您的 bean 具有更广泛的范围,或者您想要更细粒度的验证/转换,请使用 在目标视图上,另见 f:viewParam vs @ManagedProperty:

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

无论哪种方式,这样做的优点是不必为表单提交保留数据模型(对于您的 bean 是请求范围的情况).

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

使用UICommand 组件中.优点是当 bean 的范围比请求范围更广时,这消除了访问请求参数映射的需要.

Use <f:setPropertyActionListener> in UICommand component. 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>

结合

 private Long id; // +setter

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

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.

将数据表值绑定到 DataModel 而不是它反过来包装项目.

Bind the datatable value to DataModel<E> instead which in turn wraps the items.

 <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 上使用它时,必须使其 transient 并在 getter 中延迟实例化它,因为 DataModel 没有"t 实现Serializable)

(making it transient and lazily instantiating it in the getter is mandatory when you're using this on a view or session scoped bean since DataModel doesn't implement Serializable)

然后您就可以通过 DataModel#getRowData() 不传递任何东西(JSF 根据单击的命令链接/按钮的请求参数名称确定行).

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();
     // ...
 }

这也要求为表单提交请求保留数据模型.最好是通过 @ViewScoped 将 bean 放入视图范围.

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.

使用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.

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 #1 or, when you'd like to support servlet 2.5 containers as well, with #2.

这篇关于如何将选定的行传递给 dataTable 或 ui:repeat 中的 commandLink?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆