webtier@glassfish.java.net

JSF 2 ajax and forms nested in data table problem

From: <webtier_at_javadesktop.org>
Date: Fri, 11 Dec 2009 02:09:55 PST

Hi,
 I have the following problem when using JSF 2 and ajax. I use data table to display collection elements. Each row displays information
about some item and has input field to enter quantity. For each table row we have one ItemBean instance which provides the data.
When "Add to cart" button is pressed ajax request is formed and as result addToCart method of the appropriate ItemBean instance is called.
The class ItemBean has field quantity which should be updated before the method is called. But the field is not updated nor the associated jsf validator is triggered. What could be the reason for this behaviour ?

Note: if we use standard request instead of ajax one everything works fine.

Here is the page fragment:

<h:head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <title>Ajax-JSF virtual shop</title>
</h:head>

<h:body>
<h:outputScript name="jsf.js" library="javax.faces" target="head"/>

<h:dataTable id="items" value="#{itemCollectionBean.items}" var="itemBean" width="75%" border="1">
        <h:column>
                <f:facet name="header">Item</f:facet>
                #{itemBean.item.name}
        </h:column>
        <h:column>
                <f:facet name="header">Price</f:facet>
                #{itemBean.item.price}
        </h:column>
[b] <h:column>
                <h:form id="addToCartForm">
                        <h:inputText id="quantity" value="#{itemBean.quantity}">
                                 <f:validateLongRange maximum="20" minimum="1" />
                        </h:inputText>
                                                                
                        <h:message for="quantity" />
                                                                
                        <h:commandButton
                                id="addToCart" value="Add to cart" action="#{itemBean.addToCart}"
                                onclick="jsf.ajax.request(this, event, {execute:'addToCartForm', render:'cartForm addToCartForm'}); return false;"
                        />
                </h:form>
        </h:column>[/b]
</h:dataTable>

...

Here are the managed beans used in the page fragment:

@ManagedBean
@ApplicationScoped
public class ItemCollectionBean {

        private Collection<ItemBean> items = new ArrayList<ItemBean>();
        
        public ItemCollectionBean() {
                System.out.println( "Creating items collection" );
                
                items.add(
                                new ItemBean(
                                        new Item("big beer", new BigDecimal(20), "The biggest beer")
                                )
                        );
                items.add(
                                new ItemBean(
                                        new Item("chery lady", new BigDecimal(200), "Ultra sweet")
                                )
                        );
                
                items.add(
                                new ItemBean(
                                        new Item("ultra sweet", new BigDecimal(15), "Something sweet for you")
                                )
                        );
                
        }

        public Collection<ItemBean> getItems() {
                return items;
        }
}


public class ItemBean {

        private int quantity;
        
        private Item item;
        
        public ItemBean(Item item) {
                this.item = item;
        }
        
        public void addToCart() {
                
                System.out.println("Adding to cart: " + item.getName() + " -quantity: " + quantity);
                
                // buisiness logic here
        }
        
        
        @Override
        public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + item.hashCode();
                return result;
        }

        @Override
        public boolean equals(Object obj) {
                if (this == obj)
                        return true;
                if (obj == null)
                        return false;
                if (getClass() != obj.getClass())
                        return false;
                ItemBean other = (ItemBean) obj;
                return item.equals(other.item);
        }

        public Item getItem() {
                return item;
        }

        public void setItem(Item item) {
                this.item = item;
        }

        public int getQuantity() {
                return quantity;
        }

        public void setQuantity(int quantity) {
                this.quantity = quantity;
        }
}
[Message sent by forum member 'joro_georgiev' ]

http://forums.java.net/jive/thread.jspa?messageID=375926