I have been trying to get a really simple example to work with myfaces but had zero success till now. I am hoping someone who understands jsf better than me (which is probably most of you :-)) could shed some insight into this.  Sorry for the long post, but I thought it is better to give all the details in order to explain myself.

Here is what I am trying to do. Basically I am staring out with a simple screen that presents the user with four empty rows to enter the Box's (product) height and width. The user can choose to add more rows by clicking on the Add more button. Once the user is done filling all the product he needs (user can fill as many rows as he wants), he will submit. But I am stuck for more than 5 hours on trying to get Add more button to work.  In short, what I don't understand is how is the form getting populated. Initially when the screen is displayed, I am creating four empty beans( see code below) so that I can get corresponding four empty rows initially in the data table tag (is this a good way to display empty rows, given that whatever data user puts in needs to go back into my product bean).

Additionally, I am expecting that when I hit on an action button "Add More", the four beans data (if the user has already filled in some row data) will be set on my backing bean. Further, I can just attach the extra bean as needed in my addMore method to the existing set, this way I won't loose the user entered data. (Again see code below it will be much clearer). But for some reason, the addMore is not called at all. I have the product display bean stored in the session
<managed-bean>
    <managed-bean-name>productDisplayBean</managed-bean-name>
    <managed-bean-class>com.riceint.ProductDisplayBean
    </managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

What I don't understand is if I remove the part where I am creating the four empty beans in the getProductDataModel method(See code below), then addMore does get called when the "Add More" button is clicked (else it is not). So it seems that initializing the productDataModel is messing up some kind of JSF states. I do see that when the form is submitted via clicking "Add More" , the getProductDataModel/followed by setProductDataModel is called.  This does not jibe with the way I expected it to work. I would have expected that all the product beans would be populated based on the user chocies,  and those beans will be put into the productDataModel since I am iterating over productDataModel in the t:dataTableTag. Finally JSF would have populated my productDataBean variable before the "addMore" method was called.  But none of those is happening; even the setProductDataModel is setting an empty data model. Strange. I guess I am fundamentally confused in terms of how the data model data is applied back to the backing beans. Isn't it every row data is updated in the backing bean?

Anyway here is the code below

Here is a snippet of my JSP

<%@ page session="false" contentType="text/html;charset=utf-8"%>
<%@ taglib uri=" http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri=" http://myfaces.apache.org/tomahawk" prefix="t"%>
<f:view>
    <h:form id="product_display">
<t:dataTable id="data" styleClass="standardTable"
            headerClass="standardTable_Header" footerClass="standardTable_Header"
            rowClasses="standardTable_Row1,standardTable_Row2"
            columnClasses="standardTable_Column" var="pData"
            value="#{productDisplayBean.productDataModel}"
            preserveDataModel="false">
            <h:column >
                <f:facet name="header">
                    <h:outputText value="Width" />
                </f:facet>
                <h:inputText id="width" value="#{pData.width}" size="3" >
                   <f:validateLongRange minimum="1" maximum="500" />
                </h:inputText>
            </h:column>
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Height" />
                </f:facet>
                <h:inputText id="height" value="#{pData.height}"  size="3">
                   <f:validateLongRange minimum="1" maximum="500" />
                </h:inputText>
            </h:column>
             <!-- have some more columns here -->
      </t:dataTable>
        <BR/> <BR/>
        <h:commandButton value="Add More" action="" productDisplayBean.addMore}"/>
       
        <h:commandButton value="Submit" action="">    </h:form>
    <jsp:include page="inc/mbean_source.jsp" />
</f:view>

Now given this JSP, I have a backing bean that looks like this.
public class ProductDisplayBean {
    private DataModel productDataModel;
   
    public void addMoreProductBeans(int howMany) {
        //Instantiate the EMPTY BEANs
        ProductBean[] beans = new ProductBean[howMany];
        for (int i = 0; i < beans.length; i++) {
            beans[i] = new ProductBean();
        }

        //Attach it to the data model
        if(productDataModel == null || productDataModel.getWrappedData() == null) {
            productDataModel = new ListDataModel(new ArrayList(Arrays.asList (beans)));
        }  else {
            ((List)productDataModel.getWrappedData()).addAll(new ArrayList(Arrays.asList(beans)));
        }
    }
   
    public DataModel getProductDataModel() {

        if(productDataModel == null) {    //This is done in order to start with 4 empty rows when the screen is displayed for the first time

           //if we don't do this adding beans here, the addMore function is called properly when the user clicks on the button. But adding this line
           //is confusing JSF
            addMoreProductBeans(4);
        }
        return productDataModel;
    }

    public void setProductDataModel(DataModel productDataModel) {
        this.productDataModel = productDataModel;
    }

    public String addMore() {
        addMoreProductBeans(2);
        return null; //forward it to the same page
    }

}

The ProductBean class is simply a java bean with 2 setters and getters, and is a serializable class.

Any help would be greatly appreciated.

Thanks

Reply via email to