2

I have a problem with JSF commandLink inside a datatable. I can not get it to work.

My bean is in a request scope, my action class is also in a request scope. Here is my datatable:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<HTML xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/html">
    <ui:include src="../blocks/head.xhtml"/>

    <body>
    <ui:include src="../blocks/header.xhtml"/>

    <div class="content_table" align="center">

        <h:dataTable headerClass="data_table_header"
                     cellpadding="10"
                     rowClasses="dataTableRow1,dataTableRow2"
                     value="#{searchBean.searchResult.corpusInfos}"
                     var="corpusInfo">

            <h:column>
                <f:facet name="header">
                    #{msg['application.corpusInfoTable.corpusPart']}
                </f:facet>
                #{corpusInfo.corpusPart}
            </h:column>

            <h:column>
                <f:facet name="header">
                    #{msg['application.corpusInfoTable.totalWords']}
                </f:facet>
                #{corpusInfo.allWordsCount}
            </h:column>

            <h:column>
                <f:facet name="header">
                    #{msg['application.corpusInfoTable.request']}
                </f:facet>

                <h:form id="idSimpleSearchForm">
                    <h:commandLink id="idSimpleSearchFromTable" action="#{searchAction.processSearch}"
                                   value="#{corpusInfo.searchTerm}">
                        <f:setPropertyActionListener value="50" target="#{searchBean.lineLength}"/>
                        <f:setPropertyActionListener value="simpleSearch" target="#{searchBean.searchType}"/>
                        <f:ajax execute="@form"/>
                    </h:commandLink>
                </h:form>

            </h:column>

            <h:column>
                <f:facet name="header">
                    #{msg['application.corpusInfoTable.usageNumber']}
                </f:facet>
                #{corpusInfo.usageCount}
            </h:column>

            <h:column>
                <f:facet name="header">
                    #{msg['application.corpusInfoTable.analyzedSourcesCount']}
                </f:facet>
                #{corpusInfo.analyzedSourcesCount}
            </h:column>

        </h:dataTable>

    </div>

    <ui:include src="../blocks/footer.xhtml"/>
    </body>
</f:view>
</HTML>

I have tried to change the scope of action class and bean to session or view. No success. The page just refreshes when I click the generated link.

This table gets generated from my previous request. First page contains some fields and action button, when action button is click action class is reached the needed data is set to bean class and passed to the following xhtml page where this datatable is. I see all values at the table in the right order, it is all ok except the action link.

Any ideas on how to solve this?

EDITED:

I put all page in which data table is. Maybe there is something wrong with other tags? Maybe they changes the view? Navigation to this page is written in faces-config.xml file like this:

<navigation-rule>
    <navigation-case>
        <from-action>#{searchAction.processSearch}</from-action>
        <from-outcome>success_simple_search</from-outcome>
        <to-view-id>/views/concordance/concordance.xhtml</to-view-id>
    </navigation-case>

    <navigation-case>
        <from-action>#{searchAction.processSearch}</from-action>
        <from-outcome>failure</from-outcome>
        <to-view-id>/views/error/unexpectedError.xhtml</to-view-id>
    </navigation-case>
</navigation-rule>
Paulius Matulionis
  • 23,085
  • 22
  • 103
  • 143

1 Answers1

3

That can happen if the #{searchBean.searchResult.corpusInfos} doesn't return the same list during processing the form submit as it did during displaying the page with the form.

You need to put the #{searchBean} in the view scope to ensure that the list is preserved in the view.

@ManagedBean
@ViewScoped
public class SearchBean {}

You need to make sure that you aren't doing any business logic in the getter methods of #{searchBean.searchResult} and #{searchBean.searchResult.corpusInfos}. So they should solely look like this

public SearchResult getSearchResult() {
    return searchResult;
}

and

public List<CorpusInfo> getCorpusInfos() {
    return corpusInfos;
}

If you need to preload/prefill them based on initial request or on an action, you need to do the business job in the (post)constructor or the action(listener) method instead.

See also

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I have added the SearchBean in viewscope, but now no data is presented in a table at all. I see just a table header and no values. My getters and setter does not contain any bussines logic as well. – Paulius Matulionis May 04 '12 at 19:33
  • Apparently you're changing the view or sending a redirect after collecting the results. This way the view scoped bean will be trashed. You should present the table in the same view as the search form. Something like as in this example: http://stackoverflow.com/questions/9803951/commandbutton-issue-in-jsf/9805812#9805812 – BalusC May 04 '12 at 19:39
  • I have edited my question, please take a look, maybe it will help more. – Paulius Matulionis May 04 '12 at 19:54
  • You should return to the same view. – BalusC May 04 '12 at 20:02
  • So there is no other way to make a flow for e.g. with free xhtml pages if I want to use datatable and commandLinks inside datatable? What I want to do I need to make a flow for e.g. Page1 -> Page2 -> Page3. Page2 contains datatable with commandLink inside wich points to Page3. – Paulius Matulionis May 04 '12 at 20:09
  • If you want page-to-page navigation, use normal GET requests, not POST requests. If you need POST, just return to the same page and render the content conditionally, otherwise let POST send a redirect. You've just a design mistake here, perhaps you were reading too much outdated JSF 1.x targeted resources? – BalusC May 04 '12 at 20:11
  • I tried to render the content conditionally in the same view. But when the bean is in view scope, after submitting the button, it renders the same form before submitting the button. If I change scope to request rendering is successful, but the commandLink click renders me the first form not third. Which is in the same view (same xhtml). Rendering depends on some boolean values which are set in action class depending on request. – Paulius Matulionis May 04 '12 at 20:55
  • Are you using JSF or CDI to manage the beans? The view scope works only on JSF managed beans. – BalusC May 04 '12 at 20:56
  • I do not know what is CDI at all. I am using annotations @ManagedBean from javax.faces.bean package. How to know which one is used? – Paulius Matulionis May 04 '12 at 21:05
  • Okay. That's a JSF managed bean. Are you sure that you're returning `null` or `void` on action method? Otherwise the view will be recreated. – BalusC May 04 '12 at 21:07
  • Finally! Many thanks to you for your patience. I was returning string in my action method. I changed it to void and now it works with view scope. Thanks again! – Paulius Matulionis May 04 '12 at 21:11