csharp
csharp

Reputation: 542

Problems getting Ajax to work

I am having a lot of problems getting Ajax to work properly. Part of my xhtml file is as follows:

<h:panelGrid columns="3">   
    <h:outputText value="Name of photometric system: "/>   
    <h:inputText size="20" id="namePhotSystem" value="#{filters.photometricSystem}"/>   
    <h:commandButton type="button" value="File Format" onclick="openPopup(570,570,'htmlPopup/fileFormat');" styleClass="longButton"/>   
    <h:commandButton value="Update Number of Filters">   
        <f:ajax event="mouseup" execute="@this" listener="#{filters.updateNumFilters}" render="fileTable"/>   
    </h:commandButton>   
    <h:inputText size="4" id="numFilters" value="#{filters.numUserDefined}"/>   
    <h:commandButton value="Clear List" styleClass="longButton">   
        <f:ajax execute="@this" listener="#{filters.reset}" render="numFilters fileTable"/>   
    </h:commandButton>   
</h:panelGrid>   

<h:panelGrid id="uploadDisplay" rendered="#{filters.showUploadList}">   
    <p:dataTable id="fileTable" value="#{filters.uploadList}" var="up">   
        <p:column>       
            <h:outputText value="#{up.fileNumb}"/>   
        </p:column>   

        <p:column>        
            <h:outputText value="#{up.fileName}"/>   
        </p:column>   

        <p:column>   
            <h:outputText value="#{up.fileMess}"/>   
        </p:column>   
    </p:dataTable>   
</h:panelGrid>  

Basically, when you enter a number in the input with id="numFilters" and click the button "Update Number of Filters", it is supposed to display the table with the id="fileTable", or equivalently id="uploadDisplay", then when you click the next button "Clear List", it is supposed to reset the input id="numFilters" back to zero and disabled displaying the table. For now I am not concerned about the code before "Update Number of Filters".

Before I added Ajax, this all worked correctly, with the datatable displaying the number of entries corresponding to the number in the input field, and when I clicked either of the two buttons mentioned above, the display was updated correctly. However, the whole screen "flips", and other things displayed are no longer rendered in the way I want. In fact this xhtml file is included in a main file which is viewed.

I've tried adding Ajax in various ways, one of which is here, but I'm unable to get it to work correctly, either the whole screen "flips", and/or the page is not updated correctly, or not at all.

In my bean I just has two Ajax actions that are fired as follows:

public void updateNumFilters(AjaxBehaviorEvent e) {   
    // Code to set things up   
}   

public void reset(AjaxBehaviorEvent e) {   
    // Code for resetting things   
}  

Before adding Ajax, these two methods were fired by ActionEvent in each case, and had an actionListener for both command buttons, which worked correctly. For these two methods I just changed ActionEvent to AjaxBehaviorEvent, otherwise they are the same.

If anybody can help me get this problem resolved, I would be very grateful. I am still learning how to use Ajax, and am filding it difficult to understand why it is not workin g correctly, and how to fix it.


Well, I tried p:commandButton, and still could not get it to work.

I've now cut down the amount of code displayed in order to show more clearly the problem. The relevant part of my xhtml code is here:

<h:panelGrid columns="3">   
    <h:selectOneMenu id="filters" value="#{filters.filterSet}" style="height:25px; width:350px;">   
        <f:selectItems value="#{filters.filtersMap}"/>   
    </h:selectOneMenu>   
    <h:outputText value="   " escape="false"/>   

    <h:commandButton id="filterSelect" value="Update Filter Set" styleCass="longButton">   
        <f:ajax listener="#{filters.selectFilterSet}" execute="filters" render="userDefined"/>   
    </h:commandButton>   
</h:panelGrid>   

<h:panelGroup id="userDefined" rendered="#{filters.showUserDefined}">   

    <!-- Code that is rendered here -->   

</h:panelGroup>  

and the relevant part of the bean is here:

@ManagedBean(name="filters")   
@SessionScoped  
public class MyFilterBean implements Serializable {   

    private boolean showUserDefined;   

    // Lots of other code   

    public void selectFilterSet(AjaxBehaviorEvent e) {   

        // Initialization code, and determine if showUserDefined is true or false.   

    }   

    public boolean isShowUserDefined() {   
        return showUserDefined;   
    }   

    // Lots of other code and various getters and setters   
}

When the command button is clicked the Ajax event is fired and the code in that method is executed, but I'm unable to get the xhtml code rendered based on the return from isShowUserDefined().

When the code is non-Ajax and the command button is clicked firing a regular action listender, it works perfectly correctly, except that I get a "page flip", which is not wanted.

If someone could help me get this problem finally nailed, I would be veru grateful indeed.


Many thanks for your reply, and in the mean time I solved it without changing h:commandButton to p:commandButton, although elsewhere in the code PrimeFaces has been used.

Here is a more complete listing of my xhtml code, with the code previously posted and now changed between the #### and #### comments. However, I am now having problems getting Ajax to work with a menu selected item, as given near the top of the code here. I am unable to get the command button "Update Filter Set" to update properly the components given by the Ajax tag. I can of course remove the button and use a value change listender, but this will not solve the problem.

Here is the xhtml code:

    <span id="filterDetails" style="display:none;">

    <!-- This displays any warning or error messages -->

    <h:panelGrid>
      <h:outputText value="The input data do not match - possibly a '$' was omitted for user defined filters&lt;br/&gt;"
                    styleClass="error" escape="false" rendered="#{filters.error}"/>
      <h:outputText value="You are not logged in - This only simulates file uploads" rendered="#{!login.loggedIn}"
                    style="color:red; font-weight:bold;"/>
    </h:panelGrid>

    <ui:fragment rendered="#{filters.showUserDefined}">

      <!-- This is the file upload option for user defined filters when showUserDefined is true -->

      <h:panelGrid id="fileUpload">
        <p:fileUpload fileUploadListener="#{filters.upload}" allowTypes="/(\.|\/)txt$/"
                      sizeLimit="10000" update="fileTable" description="Select Text File"
                      disabled="#{!filters.showUploadList}"/>
      </h:panelGrid>

      <!-- This controls the display of user defined filters when showUserDefined is true -->

<!--#### Start of previously listed code that has been changed ####-->

      <h:panelGrid id="photsys" columns="3">
        <h:outputText value="Name of photometric system: "/>
        <h:inputText size="20" id="namePhotSystem" value="#{filters.photometricSystem}"/>
        <h:commandButton type="button" value="File Format" onclick="openPopup(570,570,'htmlPopup/fileFormat');"
                         styleClass="longButton"/>
        <h:commandButton value="Update Number of Filters">
          <f:ajax execute="numFilters" listener="#{filters.updateNumFilters}" render="fileTable"/>
        </h:commandButton>
        <h:inputText size="4" id="numFilters" value="#{filters.numUserDefined}"/>
        <h:commandButton value="Clear List" styleClass="longButton">
          <f:ajax listener="#{filters.reset}" render="numFilters fileTable"/>
        </h:commandButton>
      </h:panelGrid>

      <!-- This generates a table of uploaded user defined filter when showUserDefined is true -->

      <h:panelGrid>
        <p:dataTable id="fileTable" value="#{filters.uploadList}" var="up" styleClass="#{filters.display}">
          <p:column>    
            <h:outputText value="#{up.fileNumb}"/>
          </p:column>

          <p:column>     
            <h:outputText value="#{up.fileName}"/>
          </p:column>

          <p:column>
            <h:outputText value="#{up.fileMess}"/>
          </p:column>
        </p:dataTable>
      </h:panelGrid>

<!--#### End of previously listed code that has been changed ####-->

    </ui:fragment>

    </span>

    <!-- This generates a table of labeled input fields for filters for Option 2 only -->

    <ui:fragment rendered="#{filters.opt2}">
      <table class="filterTable">
        <tr>
          <ui:repeat value="#{filters.filterCells}" var="item" varStatus="status">
            <f:verbatim rendered="#{status.index mod 5 == 0 and status.index gt 0}">
              &lt;/tr&gt;&lt;tr&gt;
            </f:verbatim>
            <td><h:outputText value="#{item.filterPair}" escape="false"/><br/>
            <h:inputText size="4" value="#{item.userInput}"/></td>
          </ui:repeat>
        </tr>
      </table>
    </ui:fragment>

any ideas would be most welcomed - many thanks.

Upvotes: 0

Views: 477

Answers (1)

Aritz
Aritz

Reputation: 31679

You can use p:commandButton instead of JSF's built-in h:commandButton. Primefaces commandButton does his work in Ajax by default.

<p:commandButton actionListener="#{filters.updateNumFilters}" 
update="@form" id="numFilterButton" value="Update Number of Filters"/>

Basically what that's doing is calling the listener in the backing bean, after that updates the @form or whatever element you want. Be sure of course you have everything into a h:form. Take a look to the component's showcase page.

http://www.primefaces.org/showcase/ui/commandButton.jsf

Upvotes: 0

Related Questions