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

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

问题描述

我在JSF 2应用程序中使用了Primefaces。我有一个< 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> 特定于组件本身



有几种方法可以实现需求。


  1. 使用 < 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是请求范围的情况)。





  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 in action方法。这仅需要为表单提交请求保留数据模型。最好是将bean放在视图范围内,由 @ViewScoped





  3. 如果您的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一样。有关配置详细信息,请参阅此答案





  4. 将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





  5. 您可以使用 应用程序#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.

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


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


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


  4. 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 since DataModel doesn't implement Serializable)

    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.


  5. 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屋!

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