+ Start a Discussion
AdrianCCAdrianCC 

Rerender Problem and Passing Values Back to the Controller

Hello,

 

I have a small logical problem with a VF page. At least that's what I think it is - a bad design from my part.

 

The page shows a List<Wrapper>. The Wrapper inner class has a bunch of Decimal fields, all public and with {get; set}. Some are editable in the page, while others are read-only, summaries for the other fields.

public class Wrapper {
    	
    	public Decimal quantity							{
    		get; 
    		set {
    			quantity = value;
    			
    			year1 = listPrice*quantity*(100-discount)/100;
    			year2 = year1;
    			year3 = year1;
    			year4 = year1;
    			year5 = year1;
    			year6 = year1;	
    		}
    	}
    	public Decimal listPrice						{get; set;}
    	public Decimal year1;							
    	
    	public Decimal getYear1() {
    		return year1;
    	}
    	
    	public void setYear1(Decimal value) {
    		this.year1 = value;
    		this.year1Discount = (quantity*listPrice - year1)/(quantity*listPrice) * 100;
    	}
    	
    	public Decimal year2							{get; set;}
    	public Decimal year3							{get; set;}
    	public Decimal year4							{get; set;}
    	public Decimal year5							{get; set;}
    	public Decimal year6							{get; set;}
    	
    	public Decimal discount;
    	
    	public Decimal getDiscount() {
    		return discount;
    	}
    	
    	public void setDiscount(Decimal value) { 
    		this.discount = value;
			year1Discount = discount;
			year1 = quantity*listPrice*(100-discount)/100;
			year2 = year1;
			year3 = year1;
			year4 = year1;
			year5 = year1;
			if (this.isNew) {
				year6 = 0;
			} else {
				year6 = year1;	
			} 
    	}
    	public Decimal year1Discount					{get{ return (quantity * listPrice - year1)/(quantity * listPrice) * 100;} set;}
    	
        public Decimal total							{get{ return (year1 + year2 + year3 + year4 + year5 + year6).round();} set;}
    	
        public Wrapper() {
        	
        }
}

As you can see, setting the quantity will change year1 to year6, same for discount. Setting year1 will modify year1Discount.

And total will always return the sum of year1+.. year6.

 

In the page only quantity, year1-year6 and discount are editable(based on a checkbox), while listPrice, discount and year1Discount are not.

 

The page looks like this(or at least a fragment of it):

<apex:pageBlock id="newProductsBlock">
	<apex:repeat value="{!fwrapper.wrapperList}" var="wrapper" >
		<tr >
			<td> 
			    <apex:inputCheckbox value="{!wrapper.isSelected}" >
			        <apex:actionSupport event="onchange" action="{!recalculate}" reRender="newProductsBlock, summaryTable"/>
			    </apex:inputCheckbox>
			</td>
			<td>
				<apex:outputPanel rendered="{!wrapper.isSelected}">
			        <apex:inputText value="{!wrapper.quantity}" >                                                                                                  
			        	<apex:actionSupport event="onchange" action="{!recalculate}" reRender="newProductsBlock, summaryTable" />
			        </apex:inputText>
				</apex:outputPanel>
				<apex:outputPanel rendered="{!NOT(wrapper.isSelected)}">
				    <apex:outputText value="{!wrapper.quantity}" />
				</apex:outputPanel>
			</td>
			<td>
				<apex:outputPanel rendered="{!wrapper.isSelected}">
					<apex:inputText value="{!wrapper.year1}" >
				   		<apex:actionSupport event="onchange" reRender="newProductsBlock, summaryTable"/>    
					</apex:inputText>
				</apex:outputPanel>
				<apex:outputPanel rendered="{!NOT(wrapper.isSelected)}">
					<apex:outputText value="{!wrapper.year1}" />
				</apex:outputPanel>   
			</td>
			<!-- rest of the years 2 - 6 -->
			<td class="borderClass">
             	<apex:outputText value="${0,number,#,###,###,###,###,##0}">
             		<apex:param value="{!wrapper.total}"/>
             	</apex:outputText>
            </td>	
            <td class="borderClass">
				<apex:outputPanel rendered="{!wrapper.isSelected}">
					<apex:inputText value="{!wrapper.discount}" >
				   		<apex:actionSupport event="onchange" reRender="newProductsBlock, summaryTable" status="status"/>    
					</apex:inputText>
				</apex:outputPanel>
				<apex:outputPanel rendered="{!NOT(wrapper.isSelected)}">
					<apex:outputText value="{!wrapper.discount}"/>
				</apex:outputPanel>  
			</td>

			<td class="borderClass">
				<apex:outputText value="{0, number,##0.00}%">
					<apex:param value="{!wrapper.year1Discount}"/>  
				</apex:outputText>                                   
			</td>	

 

My Problem is that whenever I type in another value for year1 let's say, the pageBlock is refreshed and the year1-year6 values are computed based on discount(it's the last inputText in the table), my inputed value is lost.... Somehow the discount setter is called and this "locks up" the values for the other fields... I don't know if this is the standard functionality but I need to find a way to:

  1.  on load of page show the same values as extracted from the DB without any logic on them- ie no relations between fields
  2. changing the quantity or discount recomputes all the year1-6 values
  3. changing the year1 to year6 values modifies only the total -> here is the mind fart, right now my design will change the value based on the discount and not keep the new value....

 

Wrapping the inputtexts for the year1 to year6 in apex:actionRegions seems to do what I want, yearx keeps the value, total is recalculated. However, the value is not saved in the List<Wrapper> in the controller... when I call the method to save to DB the List, this has the old values(the new value for yearx is not present)...

 

Should I try to remove those calculations from the setters of the Wrapper? I donno, for example create a calculateDiscount() method in the controller... but how do I modify only those rows where a new discount has been inputed?

 

I feel I'm close to a solution, and maybe if I get a little sleep and food I'll see it clearer, but I wouldn't say no to any help or suggestion :)

 

Happy Tuesday!

A.