Why does JSF/AJAX skip phases?

249 views Asked by At

I have page with an initial search/h:datatable on top. It renders well and displays all the text units (tokens) which are available.

Leading each row of the search results with a button "view". This button rerenders the panel group textUnitGroup, which holds the details of this token. Now, that works just fine. I can click all the token's view button and the area is refreshed WITHOUT a page reload. With the input fields of that panel group (form in embeded) I can also persist new tokens. Works, too.

However, if I load token details into that detail form (form is rendered again), and I press the "save text" button, JSF phase 2, 3, 4 and 5 are skipped (which did not happen, when I save a new token and the "view" button has NOT been clicked before).

12:31:44,174 INFO  [org.exadel.helper] (default task-22) L:54 BEFORE RESTORE_VIEW 1
12:31:44,180 INFO  [org.exadel.helper] (default task-22) L:67 AFTER RESTORE_VIEW 1
12:31:44,181 INFO  [org.exadel.helper] (default task-22) L:54 BEFORE RENDER_RESPONSE 6
12:31:44,257 INFO  [org.exadel.helper] (default task-22) L:67 AFTER RENDER_RESPONSE 6

Somewhat changes when re-rendering the details form resp. panel group. But I don't understand why. There is NO error in the log. But it is certainly the cause of the JSF phase-skipping (otherwise the insertion of a new token would not work, too).

This is the xhtml file. Let me know if you need more.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.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"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:mywidgets="http://java.sun.com/jsf/composite/widgets"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">

<ui:composition template="/templates/overviewTemplate.xhtml">
    <!-- <ui:composition template="/templates/contentTemplate.xhtml"> -->

    <ui:define name="title">Text Administration</ui:define>

    <ui:define name="body">

        <h1>Text Administration</h1>

        <h:panelGroup layout="block" id="searchListGroup" rendered="true">

            <h:form id="listOfTextUnits">

                <h:inputText autocomplete="true" style="width: 300px"
                    value="#{textController.searchFilter}"
                    pt:placeholder="Token or text in English" pt:autofocus="true"
                    title="Search by token or text in English">
                    <f:ajax event="keyup" execute="@this" render="textTable" />
                </h:inputText>

                <p class="betweenSections" />

                <h:dataTable id="textTable"
                    value="#{textController.findTextUnitsByString()}" var="textUnit"
                    styleClass="data-table" headerClass="table-header"
                    rowClasses="table-odd-row,table-even-row">

                    <h:column>
                        <!-- column header -->
                        <f:facet name="header">Action</f:facet>
                        <!-- row record -->
                        <h:commandButton value="view" styleClass="mini"
                            action="#{textController.loadTextDetail()}">
                            <f:param name="id" value="#{textUnit.id}" />
                            <f:ajax execute="@form" render="textUnitGroup" />
                        </h:commandButton>
                    </h:column>

                    <h:column sortBy="#{textUnit.token}"
                        filterExpression="#{empty filterValue or fn:startsWith(textUnit.token, filterValue)}"
                        filterValue="#{textController.searchFilter}">
                        <f:facet name="header">Token</f:facet>
                        <h:outputText value="#{textUnit.token}" />
                    </h:column>

                    <h:column>
                        <!-- column header -->
                        <f:facet name="header">Default Text</f:facet>
                        <!-- row record -->
                        #{textUnit.defaultText}
                </h:column>

                </h:dataTable>

            </h:form>
        </h:panelGroup>

        <h:panelGroup layout="block" id="textUnitGroup"
            rendered="true">

            <h2>Text unit</h2>

            <h:form id="textUnit">
                <h:inputHidden id="id" value="#{textController.id}" />

                <label for="token">Token</label>
                <h:inputText id="token" value="#{textController.token}"
                    required="true"
                    requiredMessage="Please insert a token string for this new translation." />

                <label for="text">Default Text</label>
                <h:inputTextarea id="text" value="#{textController.text}"
                    required="true"
                    requiredMessage="Please insert a default text translation."
                    cols="100" />

                <h:commandButton value="save text"
                    action="#{textController.saveText()}">
                    <f:ajax execute="@form" render="searchListGroup" />
                </h:commandButton>

            </h:form>

        </h:panelGroup>

        <p class="betweenSections" />

    </ui:define>
</ui:composition>
</html>

Thanks for any hint

--------------------------------UPDATE-------------------------------

Assuming that something with the JavaScript code has gone broken, I did put the h:panelGroup within the h:form tags. Now that works. The drawback with this is, that the h2 tags is never rerendered erspectively shown. This is what I wanted in the next step. Hide the form and then display, when needed.

To properly rephrase the question: How could one re-render a panelgroup which contains multiple h:form whitout listing all the forms in the render attribute of the f:ajax tag? Not possible at all?

Thanks for any hint!

0

There are 0 answers