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
MasahiroYMasahiroY 

InputField as Contact lookup field from my Visualforce page to Controller

I am trying to pass the value of an inputfield as Contact lookup field (Opportunity.Contact__c) from my Visualforce page (standardController = Opportunity) to my controller. 

I still don't figure out how the controller can receive the value from that Lookup value and its ID. It seems the Lookup field the datatype seems sObject, but Contact email_recipient can't receive it.

Similar post here but it doesn't help me, since I use the InputField value preset from Opportunity.Contact__c (Contact Lookup filed)
https://developer.salesforce.com/forums/?id=906F0000000MMDoIAO

Thanks for help!

VF (snippet)
<apex:form >
<apex:inputText html-placeholder="Subject" id="email_subject" value="{!email_subject}" />
<apex:inputtextarea html-placeholder="Body" rows="15" id="email_body" value="{!email_body}" />
<apex:inputField html-placeholder="Billing Contact" id="email_recipient" value="{!Opportunity.Contact__c}" />
<!-- this inputField value is from Contact Lookup filed of the Opportunity. This might be the cause of issue?? -->
          
<apex:pageBlock id="actions"> 
    <apex:param name="email_subjectText" assignTo="{!email_subject}" value="Authorization PDF"/>
    <apex:param name="email_body" assignTo="{!email_body}" value="Authorization PDF"/>
    <apex:commandButton action="{!SendPdf}" value="Send PDF"/>
</apex:pageBlock> 
</apex:form>
Controller (snippet)
public with sharing class PdfGeneratorController {
	public String email_subject {get;set;}
    public String email_body {get;set;}
    public String cont_email {get;set;}
	public Contact email_recipient {get;set;}

// this block turns error Compile Error: Illegal assignment from Schema.SObjectField to Contact
    email_recipient = new Contact();
    email_recipient = Opportunity.Contact__c;  // this might be wrong?
    cont_email = email_recipient.Email;
//

    public PageReference SendPdf() { 
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            mail.setToAddresses(new String[] {cont_email});
            mail.setSubject(email_subject);
            mail.setPlainTextBody(email_body);
            mail.setWhatId(parentId);
            mail.setEntityAttachments(Ids);
            Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});       
    }
}
Actual VF page look like. (red text is what's in VF code)
User-added image

 
Best Answer chosen by MasahiroY
Abhishek BansalAbhishek Bansal
Hi,

If this field is directly binded to the Opportunity record than you do not need to query the Contact record again. I thought you need to assign this contact values to some other record that's why I told you to query the record. 
You can update your code like below to avoid SOQL:
public Opportunity oppt {get;set;}

//In constructor add the following line:
oppt = (Opportunity) ctrl.getRecord(); 

public void contLookup(){
    //Opportunity oppt = (Opportunity) ctrl.getRecord();    
    //Contact cont = [SELECT id,Email FROM Contact WHERE Id = :oppt.Contact__c];
    //oppt.Contact__c = cont.id;
    update oppt;

// PDF in iframe with new oppt after update

    PageReference pdf = Page.test_VF2; 
    pdf.getParameters().put('id',parentId);
        
    oppt = [SELECT id,Name FROM Opportunity WHERE Id=:parentId];

    pdfname = oppt.Name + ' ['+system.today()']';
        
    Blob body; //create a blob for the PDF content
        if (!Test.isRunningTest()) { 
                body = pdf.getContent(); 
                paramvalue = EncodingUtil.base64Encode(body); 
            } else { 
                 body = Blob.valueOf('Some Text for a boring PDF file...');
            }
    }

Update VF page like below:
<apex:actionRegion>
    <apex:inputField id="email_recipient" value="{!oppt.Contact__c}">                    
        <apex:actionSupport event="onchange" action="{!contLookup}" status="status"/>                    
    </apex:inputField>
</apex:actionRegion>

I am not able to see the video so not sure what issue you are facing but hopefully these changes will resolve your issue.

Thanks,
Abhishek Bansal.

All Answers

Abhishek BansalAbhishek Bansal
Hi ,

The lookup field will display the name at the front end but in the back end it will only store the id of the related contact. You need to query the related record based on the id and than you can assign the values to the other record.
I have updated your code, please find the updated code below:
this block turns error Compile Error: Illegal assignment from Schema.SObjectField to Contact
email_recipient = new Contact();
email_recipient = Opportunity.Contact__c;  // this might be wrong?
cont_email = email_recipient.Email;

//This whole code needs to go inside a method:

public void saveRecord() {
	Contact selectedContact = [Select Name, Email from Contact where Id =: Opportunity.Contact__c];
	email_recipient = new Contact();
	email_recipient.Name = selectedContact.Name;
	email_recipient.Email = selectedContact.Email;
}

Let me know if you need any other help on this.

Thanks,
Abhishek Bansal.
Gmail: abhibansal2790@gmail.com
Skype: abhishek.bansal2790
Phone: +917357512102
MasahiroYMasahiroY
Thank you, Abhishek!
I'll tweak my code and see how it goes. Will get back to you here once I confirm the change is working.
MasahiroYMasahiroY
Hi Abhishek, 

I took your advice and included the codes inside teh method. With <apex:ActionSupport> and <apex:ActionRegion> I successfully reflect the change of Lookup Contact, and pass the ID to the other method inside the Class. Yay! 

Only problem is I get rejected to store value from inputFiled value="{Opportunity.Contact__c}" in Contact cont. So I put the {oppt.Contact__c}. But this caused the glitch. 

That glitch is the change sometimes reflects on PDF blob, sometime doesn't. It doesn't affect the send PDF anyway (demo)
https://drive.google.com/file/d/1psmjudwdTb6u13_58aSTRFxd6cNaZjXh/view?usp=sharing

VF <apex:actionSupport> on Recipient Lookup
<apex:actionRegion>
    <apex:inputField id="email_recipient" value="{!Opportunity.Contact__c}"
        <apex:actionSupport event="onchange" action="{!contLookup}" status="status"/>
    </apex:inputField>
</apex:actionRegion>
Method (called by onchange)
public void contLookup(){
    Opportunity oppt = (Opportunity) ctrl.getRecord(); 
    Contact cont = [SELECT id,Email FROM Contact WHERE Id = :oppt.Contact__c]; 
    oppt.Contact__c = cont.id; 
    update oppt; // PDF in iframe with new oppt after update

    PageReference pdf = Page.test_VF2; 
    pdf.getParameters().put('id',parentId); 
    
    oppt = [SELECT id,Name FROM Opportunity WHERE Id=:parentId]; 
    pdfname = oppt.Name + ' ['+system.today()']'; 
    
    Blob body; //create a blob for the PDF content   
    if (!Test.isRunningTest()) {
    body = pdf.getContent(); 
    paramvalue =EncodingUtil.base64Encode(body); 
    } 
    else { 
    body = Blob.valueOf('Some Text for a boring PDF file...');
    }
}
Abhishek BansalAbhishek Bansal
Hi,

If this field is directly binded to the Opportunity record than you do not need to query the Contact record again. I thought you need to assign this contact values to some other record that's why I told you to query the record. 
You can update your code like below to avoid SOQL:
public Opportunity oppt {get;set;}

//In constructor add the following line:
oppt = (Opportunity) ctrl.getRecord(); 

public void contLookup(){
    //Opportunity oppt = (Opportunity) ctrl.getRecord();    
    //Contact cont = [SELECT id,Email FROM Contact WHERE Id = :oppt.Contact__c];
    //oppt.Contact__c = cont.id;
    update oppt;

// PDF in iframe with new oppt after update

    PageReference pdf = Page.test_VF2; 
    pdf.getParameters().put('id',parentId);
        
    oppt = [SELECT id,Name FROM Opportunity WHERE Id=:parentId];

    pdfname = oppt.Name + ' ['+system.today()']';
        
    Blob body; //create a blob for the PDF content
        if (!Test.isRunningTest()) { 
                body = pdf.getContent(); 
                paramvalue = EncodingUtil.base64Encode(body); 
            } else { 
                 body = Blob.valueOf('Some Text for a boring PDF file...');
            }
    }

Update VF page like below:
<apex:actionRegion>
    <apex:inputField id="email_recipient" value="{!oppt.Contact__c}">                    
        <apex:actionSupport event="onchange" action="{!contLookup}" status="status"/>                    
    </apex:inputField>
</apex:actionRegion>

I am not able to see the video so not sure what issue you are facing but hopefully these changes will resolve your issue.

Thanks,
Abhishek Bansal.
This was selected as the best answer
MasahiroYMasahiroY
Hi Abhishek Bansal, thanks for your comment.

I changed in VF side:
<apex:inputField id="email_recipient" value="{!oppt.Contact__c}">
then shows the error:
SObject row was retrieved via SOQL without querying the requested field: Opportunity.Contact__c
An unexpected error has occurred. Your development organization has been notified.​​​​​​​


 
Abhishek BansalAbhishek Bansal
You need to query thi field from database. Please update the code:
//In constructor add the following line:
oppt = (Opportunity) ctrl.getRecord(); 
oppt = [Select Id,Name,Contact__c from Opportunity where Id =: oppt.Id];
This will resolve the above error.
MasahiroYMasahiroY
Hi Abhishek,

Thank you for your support and patience.

The PDF still gets the old contact info when you switch the contact in visualforce page. (strangely not always, sometimes) the following is the public sharing link of the screen demo how it looks, hope you can view this time.
https://drive.google.com/file/d/1I0h7IADvEtWmSh60oG9uhCW2KKjRzULM/view?usp=sharing

​​​​​​​Probably PDF blob is not taking new contact that is changed?
Here's current controller and method:
public with sharing class PdfGeneratorController {

    public ID parentId {get;set;}
    public Opportunity oppt {get;set;}
    
    public ID contId {get;set;}
    public Contact cont {get;set;}
    public Contact email_recipient {get;set;}
    private ApexPages.StandardController ctrl;

    public String email_subject {get;set;}
    public String email_body {get;set;}
    public String cont_email {get;set;}

    public Blob body {get;set;}  
    public String paramvalue {get;set;} 
    public String pdfname; 
    public ContentVersion conVer {get;set;} 
    public Id conDoc {get;set;} 
    public ContentDocumentLink conDocLink {get;set;} 
        
    public PdfGeneratorController(ApexPages.StandardController standardPageController) {
        oppt = (Opportunity)standardPageController.getRecord(); 
        oppt = [Select Id,Name,Contact__c from Opportunity where Id =: oppt.Id];
        
        parentId = oppt.id;
        contId = oppt.Contact__c;          
        
        PageReference pdf = Page.test_VF2; 
        pdf.getParameters().put('id',parentId);
       
        oppt = new Opportunity();
        oppt = [SELECT id,Name,AccountName__c,Contact__c FROM Opportunity WHERE Id=:parentId];
        pdfname = oppt.Name + ' ['+system.today()']'; 
        ctrl = standardPageController;
               
        Blob body; 
            if (!Test.isRunningTest()) { 
                body = pdf.getContent(); 
                paramvalue = EncodingUtil.base64Encode(body); 
            } else { 
                body = Blob.valueOf('Some Text for a boring PDF file...');
            }
            
    } 
    
    public void contLookup(){
        update oppt;        
        PageReference pdf = Page.test_VF2; 
        pdf.getParameters().put('id',parentId);        
        oppt = [SELECT id,Name,AccountName__c,Contact__c FROM Opportunity WHERE Id=:parentId];
​​​​​​​        pdfname = oppt.Name + ' ['+system.today()']';         
        Blob body; 
            if (!Test.isRunningTest()) { 
                body = pdf.getContent(); 
                paramvalue = EncodingUtil.base64Encode(body); 
            } else { 
                body = Blob.valueOf('Some Text for a boring PDF file...');
            }
    }  
}

VF: 
<apex:actionRegion >
   <apex:inputField html-placeholder="Billing Contact" id="email_recipient" value="{!oppt.Contact__c}">                    
 <apex:actionSupport event="onchange" action="{!contLookup}" status="status"/>                    
   </apex:inputField>
</apex:actionRegion>


 
Abhishek BansalAbhishek Bansal
Strange but still I am not able to access this recording.
If possible can we connect on a call to sort out this. You can contact me on:
Gmail: abhibansal2790@gmail.com
Skype: abhishek.bansal2790
Phone: +917357512102
MasahiroYMasahiroY
Hi Abhishek,

That's wieird. The link should be available. I'll try Dropbox.
https://www.dropbox.com/s/3sko94t2d0zw932/contact_swap.mov?dl=0

if you can't access, never mind. It's just a small issue the most of tricky part was solved by your help.