By Michael Borgwardt

2011-02-14 16:17:51 8 Comments

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:commandLink actionListener="#{bean.insert}" value="insert">
            <f:attribute name="id" value="#{}" />

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?


@EpicPandaForce 2015-04-20 20:21:10

Thanks to this site by Mkyong, the only solution that actually worked for us to pass a parameter was this

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


public String editAction() {

  Map<String,String> params = 
  String idString = params.get("myId");
  long id = Long.parseLong(idString);

Technically, that you cannot pass to the method itself directly, but to the JSF request parameter map.

@BalusC 2015-04-21 07:15:52

You've a different problem than asked here. You want to retain request parameters from #{param} map for subsequent requests, not to pass an arbitrary parameter. Your Q&A is covered by

@BalusC 2011-02-14 16:54:55

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="#{}" />

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

    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="#{}" 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="#{}" value="#{}" />

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


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


    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.

@Bozho 2011-02-14 17:06:30

+1, although my preference goes to #2 (if 2.5 has to be supported).

@Michael Borgwardt 2011-02-15 11:32:52

Thanks for the exhaustive answer. Unfortunately, I have to report that #1 was the only thing that worked in a filtered primefaces datatable (which is exactly the scenarion I need it for). All the others only worked on an unfiltered table. I see this more as a bug in primefaces than in your answer, though.

@BalusC 2011-02-15 11:41:25

Is the bean request or view scoped?

@Michael Borgwardt 2011-02-15 14:27:33

it's session scoped.

@BalusC 2011-02-15 14:32:07

With "filtered" you mean as in this showcase example? The symptoms indicate that the filter action take place in the client side only and that the model in the server side isn't maintained. Not sure if this is intentional. You can always leave an issue report.

@Rajat Gupta 2011-10-15 04:35:03

Very very helpful! Thanks for all your efforts, BalusC !

@Aditzu 2014-12-05 07:46:55

Your post is between the most useful posts I ever read. I used method 5 because I'm forced to use servlet 2.5. My question now is if it's possible to send a parameter with commandLink (like in your example) but using ajax?

@Arfan J 2011-05-09 08:50:05

In my view page:

<p:dataTable  ...>
<p:commandLink actionListener="#{inquirySOController.viewDetail}" 
               process="@this" update=":mainform:dialog_content"
    <h:graphicImage library="images" name="view.png"/>
    <f:param name="trxNo" value="#{['trxNo']}"/>

backing bean

 public void viewDetail(ActionEvent e) {

    String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");

    for (DTO item : list) {
        if (item.get("trxNo").toString().equals(trxNo)) {

@Aditzu 2014-12-05 08:09:44

Thanks a lot man! Works perfectly.

@Bozho 2011-02-14 16:48:50

In JSF 1.2 this was done by <f:setPropertyActionListener> (within the command component). In JSF 2.0 (EL 2.2 to be precise, thanks to BalusC) it's possible to do it like this: action="${filterList.insert(}

@BalusC 2011-02-14 16:57:17

This feature is not specific to JSF 2.0 (which can by itself run in Servlet 2.5 containers), but to EL 2.2 (which is part of Servlet 3.0).

Related Questions

Sponsored Content

7 Answered Questions

[SOLVED] How to pass all arguments passed to my bash script to a function of mine?

26 Answered Questions

[SOLVED] How do I pass a variable by reference?

0 Answered Questions

2 Answered Questions

[SOLVED] Get id from current row dataTable to link JSF Primefaces Java

0 Answered Questions

Primefaces dataTable JavaScript Callback on row selection with row number

3 Answered Questions

[SOLVED] Primefaces' commandLink works only on the first page of a dataTable

1 Answered Questions

[SOLVED] Get sibling element from PrimeFaces datatable row

1 Answered Questions

1 Answered Questions

[SOLVED] Can't get selected row of p:dataTable when used inside cc:implementation

1 Answered Questions

[SOLVED] When user click in a row (dataTable), don't select row

Sponsored Content