3

I have a bunch of custom components inside an apex:tabPanel. Each component is tasked with creating or editing an sObject passed to the comp through a wrapper class from my main page controller.

My problem is that when I use a select list with an action support to update the sObject within the controller using values derived from the selectList selection, the values are set with no problem, but when I change the values from inputFields within the components the values don't bind when I hit my save button. It's like the values are never making it to the sObject. Any suggestions?

Here's my Controller code:

public with sharing class wizard_Labor_comp_ctrlr {

//Properties

public ComponentConnector myConnector  {get; set;}

public void setMyConnector(ComponentConnector newConn){
myConnector = newConn;
}

public ComponentConnector getMyConnector(){
return myConnector;
}

public string selLaborItemId    {get; set;}
public list<SelectOption> laborOpts   {get; set;}
private map<string, Resource_Group__c> laborMap  {get; set;}
public boolean readyToSave     {get; set;}



public Proposal_Line_Item__c myLineItem  {get{
            if(myConnector == null){
             myLineItem = new Proposal_Line_Item__c();
             myLineItem.Invoice_Name__c = 'My Connector does not exist';
             return myLineItem;
            }
            else {
             if(myConnector.selectedLineItem == null){
              myLineItem = new Proposal_Line_Item__c();
              myLineItem.Invoice_Name__c = 'Selected Line Item does not exist';
              return myLineItem;
             }
             else return myConnector.selectedLineItem;

            }
           }
           set;}

public string invoiceName {get; set;}
public string quantity   {get; set;}
public string testStr      {get; set;}

//UNIVERSAL METHODS
public wizard_Labor_comp_ctrlr(){
loadSelectOptionItems();
readyToSave = false;
testStr = 'testing:';
}

public pageReference saveLineItem(){

testStr += quantity;
//myLineItem.quantity__c = decimal.valueOf(quantity);
myLineItem.Invoice_Name__c = invoiceName;

if(readyToSave){
  myConnector.saveLineItem(true);
}

return null;
}

public pageReference clearLineItem(){

myConnector.clearLineItem();

return null;
}


// SPECIFIC METHODS
private void loadSelectOptionItems(){
list<Resource_Group__c> laborList = [SELECT id, resource_group_name__c, invoice_name__c, Cost__c, Resale_Per_Day__c, Resale_Per_Hour__c, Unit_of_Measure__c, IBS_resource_Group_ID__c FROM Resource_Group__c WHERE resource_Type__c = 'Labor'];

laborOpts = new list<SelectOption>();
laborMap = new map<string, Resource_Group__c>();

for(Resource_Group__c labor : laborList){
  laborOpts.add(new SelectOption(labor.Id, labor.invoice_Name__c));
  laborMap.put(labor.Id, labor);
}
}

public void updateLaborItem(){
if(selLaborItemId != null){
  Resource_Group__c tempLabor = laborMap.get(selLaborItemId);
  string uOfM = tempLabor.Unit_of_Measure__c;


  if(myLineItem.Quantity__c == null) myLineItem.Quantity__c = 0;

  myLineItem.Invoice_Name__c = tempLabor.Invoice_Name__c;
  myLineItem.Cost__c = tempLabor.Cost__c;
  myLineItem.Unit_of_Measure__c = uOfM;

  if(uOfM == 'Hourly') myLineItem.Unit_Price__c= tempLabor.Resale_Per_Hour__c;
  else if(uOfM == 'Daily') myLineItem.Unit_Price__c = tempLabor.Resale_Per_Day__c;
  else myLineItem.Unit_Price__c = 1000000000;

  readyToSave = true;
}
}


}

And here's my component:

<table style="width:100%; background-color:#F0F2CD;">
 <tr>
  <td>Labor Item:</td>
  <td>
   <apex:selectList id="laboroptions" value="{!selLaborItemId}" size="1" multiselect="false">
    <apex:selectOptions value="{!laborOpts}"/>
    <apex:actionSupport event="onchange" action="{!updateLaborItem}" rerender="LaborTable"/>
   </apex:selectList>
  </td>
 </tr>
 <tr>
  <td>Invoice Name: </td>
  <td>
   <apex:inputField id="LaborInvoiceNameBox" value="{!myLineItem.Invoice_Name__c}"/>
   <apex:inputText id="LaborInvoiceNameBox2" value="{!invoiceName}"/>
  </td>
 </tr>
 <tr>
  <td>Quantity:</td>
  <td>
   <apex:inputField id="LaborQuantityBox" style="width:50px" value="{!myLineItem.Quantity__c}"/>
   <apex:inputText id="LaborQuantityBox2" style="width:50px" value="{!quantity}"/>

  </td>
  <td>Unit Price:</td>
  <td>
   <apex:inputField id="LaborUnitPriceBox" style="width:75px" value="{!myLineItem.Unit_Price__c}"/>
  </td>
  <td>Unit of Measure:</td>
  <td>
   <apex:outputField id="LaborUnitOfMeasureBox"  value="{!myLineItem.Unit_of_Measure__c}"/>
  </td>
 </tr>
 <tr>
  <td>
   <apex:commandButton action="{!SaveLineItem}" disabled="{!NOT(readyToSave)}" value="Save" rerender="LaborTable,previewPane"/>
   <apex:commandButton action="{!ClearLineItem}" value="Clear" rerender="LaborTable"/>
  </td>
 </tr>
 <tr>
  <td>
   {!testStr}
  </td>
 </tr>
</table>

Lastly, the component within the main Page:

2
  • is your custom component using its own controller or the controller associated with the main VF page?
    – cropredy
    Dec 23 '13 at 23:15
  • Thanks for the quick reply. It's using it's own controller. That's the one above. The main page controller creates the wrapper object and the main page passes the wrapper through attributes. Didn't think I needed to include the main controller but I can if advisable.
    – user4999
    Dec 23 '13 at 23:23
2

Here's a solution - http://books.google.com/books?id=XbT4AAAAQBAJ&pg=PT105&lpg=PT105&dq=visualforce+custom+components+action+methods&source=bl&ots=jrYsO-kF1u&sig=UoelfFsqdVf8mNw4VxMjdDGzYL8&hl=en&sa=X&ei=4eK4UuKwLIbloASy5YHYDw&ved=0CCkQ6AEwADgK#v=onepage&q=visualforce%20custom%20components%20action%20methods&f=false

You pass the action methods from the base page as arguments to the custom component's attributes. The attributes use type=ApexPages.action. This allows the custom component commandbuttons to be bound to the controller's action methods, normally available only to the main page.

This is actually pretty cool. You can see another example in the VF Developers Guide under the appendix 'Apex Classes used in Visualforce Controllers' under Action Class.

0

In your code rerender attribute has a value Labortable

<apex:selectOptions value="{!laborOpts}"/>
<apex:actionSupport event="onchange" action="{!updateLaborItem}" rerender="LaborTable"/>

I can't find any component with this ID...

you have to refresh the components to recalculate to new vales...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.