简体   繁体   中英

JSF page not reloading on form action

Please read to the end, there are many EDITS
I have this piece of JSF code:

<h:form>
    <h:dataTable class="table-striped" var="_product"
        value="#{productManager.products}"
        border="1"
        binding="#{productManager.table}">
        <h:column>
            <f:facet name="header">Product</f:facet>
            #{_product.name}
        </h:column>
        <h:column>
            <f:facet name="header">Available Units</f:facet>
            #{_product.stock}
        </h:column>
        <h:column>
            <f:facet name="header">Category</f:facet>
            #{_product.category}
        </h:column>
        <h:column>
            <f:facet name="header">Price</f:facet>
            #{_product.price}
        </h:column>
        <h:column>
            <f:facet name="header">Description</f:facet>
            #{_product.description}
        </h:column>
        <h:column>
            <f:facet name="header">Select</f:facet>
            <h:commandButton class="btn btn-primary" value="Select"
                action="#{productManager.selectProduct}"/>
        </h:column>
    </h:dataTable>
</h:form>
<h:form>
    <h:outputLabel for="productName">Selected Product: </h:outputLabel>
    <h:inputText value="#{productManager.selectedDesiredCategory}"/>
    <h:commandButton value="Filter category" action="#{productManager.filterProductsByCategory}"/>
    <h:outputText id="productName" value="#{productManager.selectedName}"/><br/>
    <h:outputLabel for="units">Units: </h:outputLabel>
    <h:inputText id="units" value="#{productManager.selectedUnits}"/>
    <h:commandButton value="Add to basket" action="#{productManager.addToBasket(accountManager.username)}"/><br/>
    <h:outputText rendered="#{productManager.availableMessages}"
        value="#{productManager.message}"/>
</h:form>

The #{productManager.filterProductsByCategory} commandbutton redirects to this java method:

public void filterProductsByCategory() {
    this.products = controller.obtainProductListByCategory(selectedDesiredCategory);
    showMessage("Filtered by selected category");
} 

Here I update the content of the products list with the new set of filtered-by-category products to display them in the view. The thing is the page is not reloading to display the new content. How is this achieved?

EDIT: The showMessage method is actually displaying in the view, so the page IS reloading, but for some reason the table is not updating. Maybe it's a problem with the data the query is returning, I'm actually researching.

EDIT: The query is returning good results, as my debugging process confirmed, but the webpage is not reloading the data properly in the table.

EDIT: I found out something really weird. This is the code the JSF page is referencing to:

public void filterProductsByCategory()
   {
      filtered = true;
      products = controller.obtainProductListByCategory(selectedDesiredCategory);
      showMessage("Filtered by selected category");
   } 

I'm now using a boolean value to actually know when I have to deliver a filtered list (See why in the code below) This is the getter of the products list:

   public List<Product> getProducts()
   {
      if(filtered)
      {
          filtered = false;
          return products;
      }
      products = controller.obtainProductList();
      return products;
   }

Here if it's true it should just send the actual filtered products variable. But for some reason it's looping again and again inside the method (even after the return statement inside the if) and sending all the products to the view again. Why is this even happening?

By default, JSF calls the getter methods as much as they're used in the view. For example, for your List<Product> products field and its respective getter, if #{productManager.products appears twice in your view ie in the Facelets code, then the getter will be executed twice as well. For this reason, getter and setter methods in managed bean should be as clean as possible and should not contain any business logic involved.

Basically, you should retrieve the product list from database once, after creating the managed bean and before the view render time. To achieve this, you can use @PostConstruct annotation to decorate a void method that will be executed after the bean is created.

In code:

@ManagedBean
@ViewScoped
public class ProductManager {
    private List<Product> products;
    @PostConstruct
    public void init() { //you can change the method name
        //if you manually handle the controller, initialize it here
        //otherwise, let it be injected by EJB, Spring, CDI
        //or whichever framework you're working with
        products = controller.obtainProductList();
    }
    public List<Product> getProducts() {
        //plain getter, as simple as this
        //no business logic AT ALL
        return this.products;
    }
    public void filterProductsByCategory() {
        filtered = true;
        products = controller.obtainProductListByCategory(selectedDesiredCategory);
        //I guess this method logs a message or something...
        showMessage("Filtered by selected category");
    }
}

More info

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM