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
David LeckenbyDavid Leckenby 

Saving Opportunity and related Contact from single Visualforce page

I have created a visualforce page that displays both opportunity and contact fields that I want users to be able to edit and save. I am using the opporutnity standard controller and added the following extension so as to be able to override (or add to) the standard save functionality with the 'SaveBoth' method (below). I have managed to be able to query the correct contact and populate the contact ID, but upon 'Save' none of the contact fields on the Visualforce page are updating.

Here is the Controller Extention
public with sharing class NewLeadControllerExtension 
{
    ApexPages.StandardController controller;
    public Opportunity oppt {get; set;}
    public Account acct {get; set;}
    public Contact cont {get; set;}

    public NewLeadControllerExtension(ApexPages.StandardController controller)
    {
        this.controller = controller;
        oppt = (Opportunity)controller.getRecord();
        acct = new Account();
        cont = new Contact();
        acct.Name = oppt.Account.Name;
        cont.Id = [SELECT Id FROM Contact WHERE Name =: acct.Name LIMIT 1].Id;
    }
    public String getTitle()
    {
        return 'The Contact ID is '+ cont.Id;
    }
    public PageReference SaveBoth()
   {
        update cont; 
        controller.Save(); 
        return null;
   }
}
Here is my visualforce page
<apex:page standardController="Opportunity" extensions="NewLeadControllerExtension">
   <p>{!title}</p>
   <apex:form >  
   <apex:pageBlock title="New Sales Leads">
   
       <apex:pageBlockButtons location="bottom">
          <apex:commandButton action="{!SaveBoth}" value="Save" rerender="section1"/>
          <apex:commandButton action="{!QuickSave}" value="QuickSave"/>
       </apex:pageBlockButtons>
   
       <apex:pageBlockSection title="Opportunity Fields" columns="2" >
          <apex:repeat value="{!$ObjectType.Opportunity.FieldSets.Opportunity_Fields}" var="field">
             <apex:inputField value="{!Opportunity[field]}"/>  
          </apex:repeat>
          <apex:outputField value="{!Opportunity.Id}"/>     
       </apex:pageBlockSection>
       
       <apex:pageBlockSection title="Contact Fields" columns="2" id="section1">
          <apex:inputField value="{!Opportunity.Account.Id}"/>
          <apex:inputField value="{!Opportunity.Account.Name}"/>
          <apex:inputField value="{!Opportunity.Account.Contact__r.Rating__c}"/>
          <apex:inputField value="{!Opportunity.Account.Contact__r.Name}"/>
          <apex:inputField value="{!Opportunity.Account.Contact__r.Id}"/>
          <apex:inputField value="{!Opportunity.Account.Contact__r.Lead_Source__c}"/>
          <apex:inputField value="{!Opportunity.Account.Contact__r.MobilePhone}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Email}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Do_you_own_an_investment_property__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Level_of_Investment__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Project_of_Interest__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Life_Cycle_Stage__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Purchase_Type__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.No_of_Bedrooms__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.First_Home_Buyer__c}"/>
          <apex:outputField value="{!Opportunity.Account.Contact__r.Call_Details__c}"/>  
       </apex:pageBlockSection>
      </apex:pageBlock>
    </apex:form>
       <apex:pageBlock title="Activity Blah">
       <apex:pageBlockSection title="Call and Email Hitory" columns="1" >
             <apex:relatedList subject="{!opportunity.account.contact__r}" list="ActivityHistories" /> 
       </apex:pageBlockSection>
       </apex:pageBlock>
       <apex:pageMessages /> 
</apex:page>
Many thanks for your help

 
Best Answer chosen by David Leckenby
JayantJayant
Can you modify this -
cont.Id = [SELECT Id FROM Contact WHERE Name =: acct.Name LIMIT 1].Id;
to
cont = [SELECT Id, Rating__c, Name, Lead_Source__c, MobilePhone FROM Contact WHERE Name =: acct.Name LIMIT 1];

and 

<apex:inputField value="{!Opportunity.Account.Contact__r.Rating__c}"/>
to
<apex:inputField value="{!cont.Rating__c}"/>
(similarly for all other input fields as well).


Also, I would suggest to query and display the ouput fields as well (you may add those to same query and display).

Is it really working ? - 
<apex:outputField value="{!Opportunity.Account.Contact__r.Level_of_Investment__c}

I am just thinking what would it output ? Contact__r is a related list. It may have any number of records, its not specified from which record the field value is to be picked.

Are you getting values for all the input and output fields ? VF can only display the fields available on calling page (standard detail page for Opportunity in this case, excluding related lists) or the ones either queried in Controller or added explicitly using Standard Controller's addFields() method in the Constructor.
 

All Answers

JayantJayant
Can you modify this -
cont.Id = [SELECT Id FROM Contact WHERE Name =: acct.Name LIMIT 1].Id;
to
cont = [SELECT Id, Rating__c, Name, Lead_Source__c, MobilePhone FROM Contact WHERE Name =: acct.Name LIMIT 1];

and 

<apex:inputField value="{!Opportunity.Account.Contact__r.Rating__c}"/>
to
<apex:inputField value="{!cont.Rating__c}"/>
(similarly for all other input fields as well).


Also, I would suggest to query and display the ouput fields as well (you may add those to same query and display).

Is it really working ? - 
<apex:outputField value="{!Opportunity.Account.Contact__r.Level_of_Investment__c}

I am just thinking what would it output ? Contact__r is a related list. It may have any number of records, its not specified from which record the field value is to be picked.

Are you getting values for all the input and output fields ? VF can only display the fields available on calling page (standard detail page for Opportunity in this case, excluding related lists) or the ones either queried in Controller or added explicitly using Standard Controller's addFields() method in the Constructor.
 
This was selected as the best answer
David LeckenbyDavid Leckenby
Thank you so much Jayant!!! - this worked.