function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
RossGRossG 

How to bind a dynamic picklist value to an actual field

In visualforce, if I've got a couple of dynamic picklists, is it possible to bind the selected value to a real standard or custom field?

In other words let's say I've got a visualforce page that overrides the Lead edit page.  This vf page has a couple dynamic picklists on it.  On selecting values in those dynamic picklists, the user would click save, and the selected values would be mapped to actual fields on the Lead object.  Not sure how to do this.

Here's a simple vf page that could override the lead edit button, along with it's custom controller.  It seems to work, except for actually saving the dynamic picklist selections to the database.

Any help is appreciated 

vf page:


<apex:page standardController="Lead" extensions="DependentObjects" id="UseCaseDisplay" label="FeatureCategoryReport">
<apex:form >
<apex:pageBlock title="New Lead" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton action="{!save}" value="Save"/>
<apex:commandButton action="{!cancel}" value="Cancel"/>

</apex:pageBlockButtons>

<apex:pageBlockSection id="section1" title="Lead Information" columns="2" collapsible="true" ondblclick="toggleInputFieldsSales();">
<apex:inputField value="{!lead.LastName}"/>
<apex:inputField value="{!lead.Email}"/>
<apex:inputField value="{!lead.Company}"/>
<apex:inputField value="{!lead.LeadSource}"/>
<apex:inputField value="{!lead.Lead_Source_Detail__c}" />
</apex:pageBlockSection>  


<apex:pageblocksection >
<table border="0" width="923px;">
  <tr>
    <td align = "right"> 
         <apex:outputLabel style="font-weight:bold;font-size:11px;" value="Lead Source" for="category"/>
         &nbsp;&nbsp;
    </td>
    <td> &nbsp;         
         <apex:selectList style="align:right;" value="{!category}" size="1" id="category">
         <apex:selectOptions value="{!categories}"/>
         <apex:actionSupport event="onchange" rerender="features"/>        
         </apex:selectList>
    </td>
  </tr>
  <tr>
     <td align = "right">
         <apex:outputLabel style="font-weight:bold;font-size:11px;" value="Lead Source Detail" for="features"/>
         &nbsp;&nbsp;
    </td>
     <td>
         &nbsp;
         <apex:selectList value="{!feature}" size="1" id="features" disabled="{!ISNULL(category)}">
         <apex:selectOptions value="{!features}"/>
         </apex:selectList>
    </td>
  </tr>
</table>  
</apex:pageBlockSection>




</apex:pageBlock>
</apex:form>
</apex:page>


controller:






public class DependentObjects {

    private final Lead acct;
    
    
    // The extension constructor initializes the private member
    // variable acct by using the getRecord method from the standard
    // controller.
    public DependentObjects(ApexPages.StandardController stdController) {
        this.acct = (Lead)stdController.getRecord();
    }
    
    public String selectedAccName {get; set;}
    public DependentObjects() {
        selectedAccName = '';
    }
    return page;
    }    
    
    
    /* String value for the category */
    String category;

    /* String value for the feature */
    String feature;

    /* Getter for the category value */
    public String getCategory() { return this.category; }

    /* Setter for the category value */
    public void setCategory(String s) { this.category = s; }

    /* Getter for the feature value */
    public String getFeature() { return this.feature; }
 
    /* Setter for the feature value */
    public void setFeature(String s) { this.feature = s; }
    
    /* Getter which dynamically generates the categories from the Feature_Category__c object. */
    public List<SelectOption> getCategories() {
      //List<SelectOption> optionList = new List<SelectOption>();
      /* Add a null option to force the user to make a selection. */
     // options.add(new SelectOption('','- None -'));
    
      /* Loop through the Lead records creating a selectOption
         for each result with the record ID as the value and the name as the label 
         displayed in the selectList */

    Set<String> uniqueCustomObjectSet = new Set<String>();    
    List<SelectOption> options = new List<SelectOption>();
          options.add(new SelectOption('','- None -'));

    for(LeadSourceHidden__c sl:[Select LeadSourceHidden__c,Name From LeadSourceHidden__c WHERE LeadSourceHidden__c != null ORDER BY LeadSourceHidden__c DESC
    ])
    {
    uniqueCustomObjectSet.add(sl.LeadSourceHidden__c);
    }
    List<String> uniqueCustomObjectList = new List<String>(uniqueCustomObjectSet);
    
    for(integer i=0; i<uniqueCustomObjectList.size(); i++){
    options.add(new SelectOption(uniqueCustomObjectList[i],uniqueCustomObjectList[i]));
    }
    
    //options.add(new SelectOption('test','test'));
    return options;
    }

    /* Getter which generates the options for the features selectList based on the current
       value of the selected category. If there is no value selected then only
       the null option should be returned. */
    
    public List<SelectOption> getFeatures() {
      List<SelectOption> optionList = new List<SelectOption>();
      /* Add a null option to force the user to make a selection. */
       optionList.add(new SelectOption('', '- None -')); 

      /* If a category has been selected then query for the related values */
      if(category != NULL) {

        /* Loop over the related campaign records for the given lead source 
           creating a selectOption with the value being the feature record ID
           and the label is the name of the lead source. */
        for (Campaign f : [select Name,Type from Campaign f where f.Type =: category LIMIT 40000 ]){
          optionList.add(new SelectOption(f.Id,f.Name));
        }
      }
      return optionList;
    }
}


Best Answer chosen by RossG
kevin Carotherskevin Carothers
Sorry Ross - I didn't mean to say trigger records -- I was working on two problems at once....  
But still, lookup values won't be populated unless you specifically query them out.  


In your constructor where there is currently the line that reads

theLead = (Lead)stdController.getRecord();

You'll have to replace it with something like this;

Leal l = (Lead)stdController.getRecord();
theLead = [SELECT ID, Category__c, Feature__c, Account__r.field1, Account__r.field2 FROM Lead where Id = l.Id];


All Answers

Sonam_SFDCSonam_SFDC
If I underdtand your usecase correctly, you can use selectlist to showcase the values for the fields in the form of a picklict and then assign this value to a property on the Controller class and then when you save this value - you can copy the value of this property to the field in the object:
http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_selectList.htm
kevin Carotherskevin Carothers
Hi Ross,

Just a couple of things;

I've had best results using an apex:actionRegion doing this.
Also - I had some problems compiling the code you posted, so I gave it a whirl to try and get it going -- and in the process, I did a lot of  rearranging.

Oh, and I took a couple fields out, but I think you shouldn't have any problems putting them back.

Hope this helps;

VF Page;
<apex:page standardController="Lead" extensions="DependentObjects" id="UseCaseDisplay"  label="FeatureCategoryReport">
<apex:form >
<apex:messages ></apex:messages>

<apex:pageBlock title="New Lead" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton action="{!save}" value="Save"/>
<apex:commandButton action="{!cancel}" value="Cancel"/>
</apex:pageBlockButtons>

<script>
 function callUpdate(){
     updateCategory('abc');
     }     
</script>

<apex:actionFunction name="updateCategory" action="{!noop}" rerender="_features"/>

<apex:pageBlockSection id="section1" title="Lead Information" columns="2" collapsible="true">
<apex:inputField value="{!lead.LastName}"/>
<apex:inputField value="{!lead.Email}"/>
<apex:inputField value="{!lead.Company}"/>
<apex:inputField value="{!lead.LeadSource}"/>
<apex:inputField value="{!lead.Lead_Source_Detail__c}" />
</apex:pageBlockSection>

<apex:pageblocksection id="_category" columns="2">
<apex:outputLabel value="Lead Category" for="category"/>      
<apex:selectList value="{!theCategory}" size="1" onChange="callUpdate();"  id="category">
   <apex:selectOptions value="{!categories}"/>
</apex:selectList>
</apex:pageBlockSection>

<apex:actionRegion >
<apex:pageblocksection id="_features" columns="2">
         <apex:outputLabel value="Lead Source Detail" for="features"/>
         <apex:selectList value="{!thefeature}" size="1" id="_features">
         <apex:selectOptions value="{!features}"/>
         </apex:selectList>
</apex:pageBlockSection>
</apex:actionRegion>

</apex:pageBlock>
</apex:form>
</apex:page>

Page Controller extension;
public class DependentObjects {
    private final Lead theLead;
    public List<SelectOption> optionList = new List<SelectOption>();
    public List<SelectOption> options = new List<SelectOption>();
    public Boolean isCategoryChosen{get; set;} 
    public String selectedAccName {get; set;}
    public String theCategory{get; set;}        /* String value for the category */
    public String theFeature{get; set;}         /* String value for the feature */
    
    public DependentObjects(ApexPages.StandardController stdController) {
        selectedAccName = '';        
        theLead = (Lead)stdController.getRecord();
        isCategoryChosen = false;
        }
  
    /* Getter which dynamically generates the categories from the Feature_Category__c object. */
    public List<SelectOption> getCategories() {
      Set<String> uniqueCustomObjectSet = new Set<String>();    
      options = new  List<SelectOption>();
      
      for(LeadSourceHidden__c sl:[Select LeadSourceHidden__c,Name 
                    From LeadSourceHidden__c 
                    WHERE LeadSourceHidden__c != null ORDER BY LeadSourceHidden__c DESC ]) {
          uniqueCustomObjectSet.add(sl.LeadSourceHidden__c);
          }

      options.add(new SelectOption('','- None -'));      // Initial value
      for(String s :uniqueCustomObjectSet){
        options.add(new SelectOption(s, s));
        }
        
      return options;
      }

    public List<SelectOption> getFeatures() {
       optionList = new List<SelectOption>();
       optionList.add(new SelectOption('', '- None -'));    /* Add a null option to force the user to make a selection. */

      if(theCategory != NULL) {   /* If a category has been selected then query for the related values */
        for (Campaign f : [select Name,Type from Campaign f where f.Type = :theCategory LIMIT 40000 ]){
          optionList.add(new SelectOption(f.Id,f.Name));
          }
        }
      isCategoryChosen = true;  
      return optionList;
    }

    public void changedFeatures() {
        optionList = new List<SelectOption>();
        getFeatures();       
        }
    
    public void setCategories() {
        }
    
     public PageReference noop() {
        ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'entered noop'));
        return null;
        }
    
    public String getCategory() { return this.theCategory; }          /* Getter for the category value */
    
    public void setFeature(String s) {       
        this.theFeature = s;
    }         /* Setter for the feature value */
    
    public String getFeature() {
        return this.theFeature;
        }            /* Getter for the feature value */
    
    public Boolean getisCategoryChosen() {
        return this.isCategoryChosen;
        }  /* Getter for the feature value */
}
There's more than one way to do it, but the actionFunction is synching the value of the onChange value with the controller, and the controller rebuilds the features list.   I changed around the look and feel too but you can mess with that too.



RossGRossG
Thanks a lot.  I tried this code but, I don't see how it is saving the selected values in the dynamic picklists to any actual database field.  Basically the idea is I want the selected picklist value in the lead source dynamic picklist to be saved to the Lead Source standard field on the lead.   Same thing with the lead source.  Thanks a lot
kevin Carotherskevin Carothers

Got it -
You have to override the save methos in your class.

VF Page;

<apex:page standardController="Lead" extensions="DependentObjects" id="UseCaseDisplay"  label="FeatureCategoryReport">
<apex:form >
<apex:messages ></apex:messages>

<apex:pageBlock title="New Lead" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton action="{!mySave}" value="Save"/>
<apex:commandButton action="{!cancel}" value="Cancel"/>
</apex:pageBlockButtons>

<script>
 function callUpdate(){
     //alert('call vupdate');
     updateCategory('abc');
     }     
</script>

<apex:actionFunction name="updateCategory" action="{!noop}" rerender="_features"/>

<apex:pageBlockSection id="section1" title="Lead Information" columns="2" collapsible="true">
<apex:inputField value="{!lead.LastName}"/>
<apex:inputField value="{!lead.Email}"/>
<apex:inputField value="{!lead.Company}"/>
<apex:inputField value="{!lead.LeadSource}"/>
<apex:inputField value="{!lead.Lead_Source_Detail__c}" />
</apex:pageBlockSection>

<apex:pageblocksection id="_category" columns="2">
<apex:outputLabel value="Lead Category" for="category"/>      
<apex:selectList value="{!theCategory}" size="1" onChange="callUpdate();"  id="category">
   <apex:selectOptions value="{!categories}"/>
</apex:selectList>
</apex:pageBlockSection>

<apex:actionRegion >
<apex:pageblocksection id="_features" columns="2">
         <apex:outputLabel value="Lead Source Detail" for="features"/>
         <apex:selectList value="{!thefeature}" size="1" id="_features">
         <apex:selectOptions value="{!features}"/>
         </apex:selectList>
</apex:pageBlockSection>
</apex:actionRegion>

</apex:pageBlock>
</apex:form>
</apex:page>

Controller;

public class DependentObjects {
    private final Lead theLead;
    public List<SelectOption> optionList = new List<SelectOption>();
    public List<SelectOption> options = new List<SelectOption>();
    public Boolean isCategoryChosen{get; set;} 
    public String selectedAccName {get; set;}
    public String theCategory{get; set;}        /* String value for the category */
    public String theFeature{get; set;}         /* String value for the feature */
    
    public DependentObjects(ApexPages.StandardController stdController) {
        selectedAccName = '';        
        theLead = (Lead)stdController.getRecord();
        isCategoryChosen = false;
        }
  
    /* Getter which dynamically generates the categories from the Feature_Category__c object. */
    public List<SelectOption> getCategories() {
      System.debug('Entered getCategories... theFeature: ' + theFeature);
      Set<String> uniqueCustomObjectSet = new Set<String>();    
      options = new  List<SelectOption>();
      
      for(LeadSourceHidden__c sl:[Select LeadSourceHidden__c,Name From LeadSourceHidden__c WHERE LeadSourceHidden__c != null ORDER BY LeadSourceHidden__c DESC ]) {
          uniqueCustomObjectSet.add(sl.LeadSourceHidden__c);
          }

      options.add(new SelectOption('','- None -'));      // Initial value
      for(String s :uniqueCustomObjectSet){
        options.add(new SelectOption(s, s));
        }
        
      return options;
      }

    public List<SelectOption> getFeatures() {
       System.debug('Entered getFeatures... theCategory: ' + theCategory);
       optionList = new List<SelectOption>();
       optionList.add(new SelectOption('', '- None -'));    /* Add a null option to force the user to make a selection. */

      if(theCategory != NULL) {   /* If a category has been selected then query for the related values */
        for (Campaign f : [select Name,Type from Campaign f where f.Type = :theCategory LIMIT 40000 ]){
          optionList.add(new SelectOption(f.Name,f.Name));
          }
        }
      isCategoryChosen = true;  
      return optionList;
    }

    public void changedFeatures() {
        System.debug('Entering changedFeatures: ' + this.theFeature);
        optionList = new List<SelectOption>();
        getFeatures();       
        }
    
    public void settheCategory(String s) {
        theLead.Category__c = s;
        System.debug('Entering setCategories: ' + s);
        }
    
     public PageReference mySave() {
        theLead.Feature__c = theFeature;
        theLead.Category__c = theCategory;
        
        if(theLead.Id == null)
            insert theLead;
        else
            update theLead;    
        
        PageReference pr = ApexPages.currentPage();
        return pr;
        }
         
     public PageReference noop() {
        System.debug('Entering noop: ');
        ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'entered noop'));
        return null;
        }
    
    public String getCategory() { return this.theCategory; }          /* Getter for the category value */
    
    public void setFeature(String s) {       
        this.theFeature = s;
        theLead.Feature__c = s;
        System.debug('settheFeature: ' + theFeature);
    }         /* Setter for the feature value */
    
    public String getFeature() {
        System.debug('getFeature: ' + theFeature);
        return this.theFeature;
        }            /* Getter for the feature value */
    
    public Boolean getisCategoryChosen() {
        System.debug('getisCategoryChosen: ' + isCategoryChosen);
        return this.isCategoryChosen;
        }  /* Getter for the feature value */
}




RossGRossG
Awesome that works perfectly.  I'm adding fields to this now but having an issue with adding a lookup field to the account table and a picklist field.  In other words, The above works fine.  But if I go to add a new field that is a lookup to the Account table, I can get it to show up using apex:inputfield, but I can't save the value that way.  And using apex:inputtext is no good for a lookup field.  Same thing for a picklist type field.

In the working code below, the field called Account is the lookup, and the fields "Title Function" and "PingOne Subscriber Status" are picklsit type fields on lead.  Any idea if it's possible to render those as lookups/picklist type fields, and allow the user to save their selection to that underlying field?  Thanks a lot for your help:

vf page:

<apex:page standardController="Lead" extensions="DependentObjects" id="UseCaseDisplay"  label="FeatureCategoryReport" >
    <apex:form >
    <apex:messages ></apex:messages>
    
    <apex:pageBlock title="New Lead" mode="edit">
    <apex:pageBlockButtons >
    <apex:commandButton action="{!submitSave}" value="Save"/>
    <apex:commandButton action="{!cancel}" value="Cancel"/>
    </apex:pageBlockButtons>
    
    <script>
     function callUpdate(){
         updateCategory('abc');
         }     
    </script>
    
    <apex:actionFunction name="updateCategory" action="{!noop}" rerender="_features"/>
    
    
    
        <apex:pageBlockSection id="section1" title="Lead Information" columns="2" collapsible="true" ondblclick="toggleInputFieldsSales();">
        
            <apex:pageblocksectionitem >
            <apex:outputLabel value="First Name" for="firstname"/>      
            <apex:inputtext value="{!FirstName}" id="firstname"/>
            </apex:pageblocksectionitem>
           
    
            <apex:pageblocksectionitem >                        
            <apex:outputLabel value="Last Name" for="lastname"/>      
            <apex:inputtext value="{!LastName}" id="lastname"/>              
            </apex:pageblocksectionitem>
            
    
        
            <apex:pageblocksectionitem helpText="The name of the company where this Lead works. Whereas the 'Account' field links to an actual Account record in our system, the 'Company' field is just a text field, and may include errors or abbreviations.">                        
            <apex:outputLabel value="Company" for="company"/>      
            <apex:inputtext value="{!Company}" id="company"/>              
            </apex:pageblocksectionitem>    
    
            <apex:pageblocksectionitem helpText="If this Lead represents a company for which an Account record has already been created, link to that Account so this Lead's Activity records can be included in Account Activity reports.">                        
            <apex:outputLabel value="Account" for="account"/>      
            <apex:inputField value="{!Account.Name}" />
            </apex:pageblocksectionitem>       
     
            <apex:pageblocksectionitem >                        
            <apex:outputLabel value="Email" for="email"/>      
            <apex:inputtext value="{!Email}" id="email"/>              
            </apex:pageblocksectionitem>
            
            <apex:pageblocksectionitem >                        
            <apex:outputLabel value="Existing Customer" for="existingcustomer"/>      
            <apex:inputCheckbox value="{!ExistingCustomer}" id="existingcustomer"/>              
            </apex:pageblocksectionitem>              
    
            <apex:pageblocksectionitem >                        
            <apex:outputLabel value="Title" for="title"/>      
            <apex:inputtext value="{!Title}" id="title"/>              
            </apex:pageblocksectionitem>   
            
            <apex:pageblocksectionitem >                        
            <apex:outputLabel value="PingOne Subscriber Status" for="PingOneSubscriberStatus"/>      
            <apex:inputtext value="{!PingOneSubscriberStatus}" id="PingOneSubscriberStatus"/>              
            </apex:pageblocksectionitem>                 
              
            <apex:pageblocksectionitem >                        
            <apex:outputLabel value="Title Function" for="titlefunction"/>      
            <apex:inputtext value="{!TitleFunction}" id="titlefunction"/>              
            </apex:pageblocksectionitem> 
    
    
    
    
    
    
        
        
        </apex:pageBlockSection>   
    
    
    
    
    
    <apex:pageblocksection id="_category" columns="2">
    <apex:outputLabel value="Lead Source" for="category"/>      
    <apex:selectList value="{!theCategory}" size="1" onChange="callUpdate();"  id="category">
       <apex:selectOptions value="{!categories}"/>
    </apex:selectList>
    </apex:pageBlockSection>
    
    <apex:actionRegion >
    <apex:pageblocksection id="_features" columns="2">
             <apex:outputLabel value="Lead Source Detail" for="features"/>
             <apex:selectList value="{!thefeature}" size="1" id="_features">
             <apex:selectOptions value="{!features}"/>
             </apex:selectList>
    </apex:pageBlockSection>
    </apex:actionRegion>
    
    </apex:pageBlock>
    </apex:form>
</apex:page>

controller:

public class DependentObjects {
    private final Lead theLead;
    public List<SelectOption> optionList = new List<SelectOption>();
    public List<SelectOption> options = new List<SelectOption>();
    public Boolean isCategoryChosen{get; set;} 
    public String selectedAccName {get; set;}
        public String LastName {get; set;}
        public String Email {get; set;}
        public String Company {get; set;}
        public String FirstName {get; set;}  
        public String PingOneSubscriberStatus {get; set;}  
        public String Owner {get; set;} 
        public String RecordType {get; set;} 
        public Account Account {get; set;}  
        public Boolean ExistingCustomer {get; set;}               
        public String Title {get; set;} 
        public String TitleFunction {get; set;}         

    public String theCategory{get; set;}        /* String value for the category */
    public String theFeature{get; set;}         /* String value for the feature */
    
    public DependentObjects(ApexPages.StandardController stdController) {
        selectedAccName = '';        
        theLead = (Lead)stdController.getRecord();
        isCategoryChosen = false;
        }
  
    /* Getter which dynamically generates the categories from the Feature_Category__c object. */
    public List<SelectOption> getCategories() {
      Set<String> uniqueCustomObjectSet = new Set<String>();    
      options = new  List<SelectOption>();
      
      for(LeadSourceHidden__c sl:[Select LeadSourceHidden__c,Name 
                    From LeadSourceHidden__c 
                    WHERE LeadSourceHidden__c != null ORDER BY LeadSourceHidden__c DESC ]) {
          uniqueCustomObjectSet.add(sl.LeadSourceHidden__c);
          }

      options.add(new SelectOption('','- None -'));      // Initial value
      for(String s :uniqueCustomObjectSet){
        options.add(new SelectOption(s, s));
        }
        
      return options;
      }

    public List<SelectOption> getFeatures() {
       optionList = new List<SelectOption>();
       optionList.add(new SelectOption('', '- None -'));    /* Add a null option to force the user to make a selection. */

      if(theCategory != NULL) {   /* If a category has been selected then query for the related values */
        for (Campaign f : [select Name,Type from Campaign f where f.Type = :theCategory LIMIT 40000 ]){
          optionList.add(new SelectOption(f.Name,f.Name));
          }
        }
      isCategoryChosen = true;  
      return optionList;
    }

    public void changedFeatures() {
        optionList = new List<SelectOption>();
        getFeatures();       
        }
    
    public void setCategories() {
        }
    
     public PageReference noop() {
        ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'entered noop'));
        return null;
        }
    
    public String getCategory() { return this.theCategory; }          /* Getter for the category value */
    
    public void setFeature(String s) {  
        this.theFeature = s;
    }         /* Setter for the feature value */
    
    public String getFeature() {
        return this.theFeature;
        }            /* Getter for the feature value */
    
    public Boolean getisCategoryChosen() {
        return this.isCategoryChosen;
        }  /* Getter for the feature value */
        
        
        
public PageReference submitSave(){

Lead  l = new Lead ();

l.LastName = LastName;
l.Email = Email;
l.Company = Company;
l.LeadSource = theCategory;
l.Lead_Source_Detail__c = theFeature;
l.FirstName = FirstName;
l.PingOne_Subscriber_Status__c = PingOneSubscriberStatus;
l.Existing_Customer__c = ExistingCustomer;
l.Title = Title;
l.Title_Function__c = TitleFunction;


insert l;
        l.clear();
        PageReference page = new PageReference('https://cs15.salesforce.com/00Q/o');
        page.setredirect(false);
        return page;
}      
        
        
        
}


kevin Carotherskevin Carothers
Sorry Ross - I didn't mean to say trigger records -- I was working on two problems at once....  
But still, lookup values won't be populated unless you specifically query them out.  


In your constructor where there is currently the line that reads

theLead = (Lead)stdController.getRecord();

You'll have to replace it with something like this;

Leal l = (Lead)stdController.getRecord();
theLead = [SELECT ID, Category__c, Feature__c, Account__r.field1, Account__r.field2 FROM Lead where Id = l.Id];


This was selected as the best answer
RossGRossG
Awesome Kevin thank you so much for your insight and help on this.  This is just terrific.

My only remaining question at this point is...what is your opinion on writing test classes on the vf page and controller above?  Do you think it is necessary in this situation to write a test class? I'm not sure, but I guess maybe it is, because I am technically setting a couple of field values when a record is inserted or updated.