I currently have a complex but structured object for my visualforce page. The object itself has multiple wrapper objects within itself, currently about 3-4 deep. For example:
public class MyOuterObject{
public Id accountId { get; set; }
public String accountName { get; set; }
public List<Invoice> invoices { get; set; }
public List<Shipment> shipments { get; set; }
public Decimal balance { get; set; }
public MyOuterObject(List<Custom__c> details){
/* Constructor setup here */
for(Custom__c c : details){
balance += c.Balance__c;
this.invoices.add( new Invoice( c ) );
}
}
}
You can see that this would instantiate a list of Shipments
as well as Invoices
which contain records of their SF custom object, but for the sake of this visualforce page are inner classes of MyOuterObject
. In addition each of these inner classes also have an inner class representing their instance's line items (I can add this code as well but don't believe it is necessary at the moment).
So these objects make up the list of outer object that are then iterated on my visualforce page like so:
<apex:repeat value="{!p.invoices}" var="i">
<!-- Single invoice -->
<apex:outputPanel layout="block">
<apex:form >
<apex:outputPanel layout="block">
<apex:outputPanel layout="block">Product</apex:outputPanel>
<apex:outputPanel layout="block">Units</apex:outputPanel>
<apex:outputPanel layout="block">Unit Cost</apex:outputPanel>
<apex:outputPanel layout="block">Total Cost</apex:outputPanel>
<apex:outputPanel layout="block">Units to Pay</apex:outputPanel>
</apex:outputPanel> <!-- /.header -->
<apex:repeat value="{!i.invoiceLineItems}" var="lineItem">
<apex:outputPanel styleClass="i-line" layout="block">
<apex:outputPanel layout="block">{!lineItem.record.Product__r.Name}</apex:outputPanel>
<apex:outputPanel layout="block">{!lineItem.record.Units_Owed__c}</apex:outputPanel>
<apex:outputPanel layout="block">${!lineItem.record.Replacement_Cost__c}</apex:outputPanel>
<apex:outputPanel layout="block">${!lineItem.record.Total_Invoiced__c}</apex:outputPanel>
<!-- HERE IS THE INPUT FIELD IN QUESTION -->
<apex:inputText value="{!lineItem.unitsToPay}" onChange="updateUnitsToPay(this)"/>
</apex:outputPanel>
</apex:repeat>
<apex:outputPanel styleClass="total-line" layout="block">
<apex:outputPanel layout="block">Remaining Balance</apex:outputPanel>
<apex:outputPanel layout="block">${!i.balance}</apex:outputPanel>
</apex:outputPanel>
<apex:outputPanel styleClass="to-pay" layout="block">
<apex:outputPanel styleClass="title" layout="block">Amount to Pay</apex:outputPanel>
<apex:outputPanel layout="block">${!i.payment}</apex:outputPanel>
</apex:outputPanel>
<apex:commandButton value="Apply Payment" action="{!processPayment}"></apex:commandButton>
</apex:form>
</apex:outputPanel>
</apex:repeat>
As a visual aid this looks like this:
My question simply put is this... How can I capture/set the value of the input field "onChange" of the input field?
At the moment I'm working on an attempt to call an actionFunction
through javascript but I'm not sure how I would manually set
the value on the "line item" instance and then rerender just that invoice section (if possible)
Also, "onChange" is the ideal interaction I want, but if I use the onchange event to convert the submit button into a "recalculate" button instead than I could do the same logic on a command button, but again there is a question of how I would set
the values to the correct line item instances.
Update/Follow up question:
So I don't even see that the setter
is firing when I submit the form through a command button. I tested this by setting up a debug on the setter like this:
public class InvoiceLineItem {
public Decimal unitsToPay { get; set{
unitsToPay = value;
System.debug('::VALUE:: '+value);
} }
/* Constuctor */
}
I see this print on page load but once I submit the form it rerenders the invoice with its original values and debug shows no trace of setting ever firing.