1
votes

I have a column with p:commandLink inside p:dataTable, which has a paginator. When user clicks on a commandLink, a dialog opens, displaying data of that row.

datatable html code:

<p:dataTable id="dtSample" value="#{sessionBean.sampleList}"
    binding="#{requestBean.dtSampleList}"
    paginator="true" paginatorPosition="bottom"
    paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
    rowsPerPageTemplate="#{10,25,50}"
    currentPageReportTemplate="({startRecord} of {totalRecords})"
    var="item" emptyMessage="No entries." rows="10" rowKey="#{item.id}">
    <p:column headerText="Id">
        <p:commandLink id="lnkSample"
            action="#{requestBean.onLinkClick(item)}"
            oncomplete="PF('dlgSample').show();"
            update="@(.dialogClass)">
            <h:outputText value="#{item.id}" />
                        </p:commandLink>
    </p:column>
    <p:column headerText="Code">
        <h:outputText value="#{item.code}" />
    </p:column>
    <p:column headerText="Description">
        <h:outputText value="#{item.descr}" />
    </p:column>
</p:dataTable>

Request bean:

public class RequestBean {

    private SessionBean sessionBean;

    private DataTable dtSampleList;

    public void init() {
        // load samle list
        loadSampleList();
    }

    public String onLinkClick(Sample sample) {
        getSessionBean().setSelectedSample(sample);
        return "success";
    }

    private void loadSampleList() {
        List<Sample> list = new ArrayList<Sample>();

        for (int i = 0; i < 100; i++) {
            Sample tmp = new Sample();
            tmp.setId(new BigDecimal(i + 1));
            tmp.setCode("code" + (i + 1));
            tmp.setDescr("desc" + (i + 1));
            list.add(tmp);
        }
        getSessionBean().setSampleList(list);

    }

// getters and setters

}

Session bean:

public class SessionBean implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<Sample> sampleList;
    private Sample selectedSample;

    // getters and setters

}

dialog html code:

<p:dialog id="dlgSample" closeOnEscape="true" widgetVar="dlgSample"
                    styleClass="dialogClass" modal="true">
    <p:panelGrid columns="1">
        <h:outputText value="Id: #{sessionBean.selectedSample.id}" />
        <h:outputText value="Code: #{sessionBean.selectedSample.code}" />
        <h:outputText value="Description: #{sessionBean.selectedSample.descr}" />
    </p:panelGrid>
</p:dialog>

When I click on a link on the first page of a datatable, link action is executed and a dialog, displaying row data, is properly refreshed. But when I move to any of the following pages of a datatable, clicking a link doesn't refresh the data in a dialog (the link action is not called, so the data in a dialog is wrong - selectedSample variable has old value). Of course when I go back to the first page of the datatable, command link works again (action method is called and data is refreshed).

What am I doing wrong? Why is action method not called on any datatable page?

I'm using Primefaces 5.2.

3

3 Answers

2
votes

Looks like the problem was in a PF dataTable component. There were first and rows attributes missing and after adding them, commandLinks on all pages work as expected.

1
votes

What am I doing wrong? Why is action method not called on any datatable page?

A common misstake leading to that behaviour is that your state is not consistent: To process the form submit, JSF will recreate the exact same view as in the prior request, and then apply the changes (execute the action)

If this new view is now different than the view before the submit was, every action is aborted and not invoked. (Different in terms of involved elements. I.e. if your commandLink was rendered="true" before submitting, it needs to be rendered="true" during the APPLY_REQUEST_VALUES-Phase).

So, from your description I would assume, that your table is falling back to page 1, which will remove any link on page 2 from the view and abort it's view action, because the element is no longer rendered.

For the same reason, links on page 1 are working, because even if your table looses track of the current page - it will render page 1, so you have the same view as before, so the submission works.

You could easily verify this, by increasing the number of elements per page and see that every link moved from page 2 to page 1 is now working.

But without seeing the whole bean I can only assume this. For easy testing, set your bean to @SessionScoped and see if this resolves it.

For more ideas, see this post: commandButton/commandLink/ajax action/listener method not invoked or input value not updated

0
votes

When putting components such as p:commandLink in a p:dataTable row, you should always specify

process="@this"

So, in your case, I would try :

 <p:commandLink id="lnkSample"
        action="#{bean.onLinkClick(item)}"
        oncomplete="PF('dlgSample').show();"
        update="@(.dialogClass)">
        <h:outputText value="#{item.id}" />
 </p:commandLink>

Doing so, you are sure that only the click on the link will be processed, and no other submission will be performed.