3

I develop an email template which calls a Visualforce component with a custom controller (controller of the custom component).

I give an opportunity Id to my custom component and I would like load data (opportunity related lists) in the custom controller but it doesn't work.

I manage to forward the opportunity Id to the custom component which assign to a controller variable but in my controller, the variable is null..

This is the email template :

<messaging:emailTemplate subject="Quote Support" recipientType="Contact" relatedToType="Opportunity">

<messaging:htmlEmailBody >

    <c:C01_SendEmailOpportunitySupport oppId="{!relatedTo.Id}" />

</messaging:htmlEmailBody>

The Visualforce component :

<apex:component controller="CC01_SendEmailOpportunitySupport" access="global">

<apex:attribute name="oppId" type="Id" description="Id of the opportunity" assignTo="{!opportunityId}"/>

...

</apex:component>

The custom controller :

public class CC01_SendEmailOpportunitySupport{

    public Id opportunityId{get;set;}
    public Opportunity theOpportunity{get; set;}
    public String theDate{get; set;}
    private DateTime theNow;
    public OpportunityContactRole theOpportunityContactRole{get; set;}

    public CC01_SendEmailOpportunitySupport(){
        System.debug('*** parameters : ' + ApexPages.currentPage().getParameters().get('oppId'));

        init();
    }

    public void init(){
        System.debug('*** opportunityId : ' + opportunityId);

        this.theOpportunity = this.getTheOpportunityById(this.opportunityId);
        System.debug('*** theOpportunity : ' + theOpportunity );

        this.theOpportunityContactRole= this.getThePrimaryContact(this.opportunityId);
        System.debug('*** theOpportunityContactRole: ' + theOpportunityContactRole);

        this.theNow = DateTime.now();
        this.TheDate = this.theNow.day() + '/' + this.theNow.month() + '/' + this.theNow.year() + ' ' + this.theNow.hour() + ':' + this.theNow.minute();
    }
}

I guess the custom controller is loaded before the variable is assigned.

Please, someone can say to me how I I can assign the variable opportunityId?

1
  • 1
    How is the emailtemplate invoked? From apex or from a workflow/process? You may not have the Opportunity in context which is why OpportunityId is null.
    – cropredy
    Commented Jun 4, 2015 at 17:39

2 Answers 2

2

Component's controller initialization is bit different to normal controllers/ extensions. In case of a component controller. As I've observed, the setters are invoked before constructor. So, you should be able to tweak your code like this:-

Component

<apex:component controller="CC01_SendEmailOpportunitySupport" access="global">

<apex:attribute name="oppId" type="Id" description="Id of the opportunity" assignTo="{!opportunityId}"/>

{!LoadData}
...

</apex:component>

Controller:

public class CC01_SendEmailOpportunitySupport{

    public Id opportunityId{get;set;}
    public Opportunity theOpportunity{get; set;}
    public String theDate{get; set;}
    private DateTime theNow;
    public OpportunityContactRole theOpportunityContactRole{get; set;}

    public string getLoadData(){

        init();
        return '';//dummy return string
    }

    public void init(){
        System.debug('*** opportunityId : ' + opportunityId);

        this.theOpportunity = this.getTheOpportunityById(this.opportunityId);
        System.debug('*** theOpportunity : ' + theOpportunity );

        this.theOpportunityContactRole= this.getThePrimaryContact(this.opportunityId);
        System.debug('*** theOpportunityContactRole: ' + theOpportunityContactRole);

        this.theNow = DateTime.now();
        this.TheDate = this.theNow.day() + '/' + this.theNow.month() + '/' + this.theNow.year() + ' ' + this.theNow.hour() + ':' + this.theNow.minute();
    }
}
0
1

Simple test : On your Visual for component add a line that says

hello opportunity Id : {!opportunityId}

<apex:component controller="CC01_SendEmailOpportunitySupport" access="global">
<apex:attribute name="oppId" type="Id" description="Id of the opportunity" assignTo="{!opportunityId}"/>
hello opportunity Id is : {!opportunityId}
</apex:component>

Go back to your template and click on Send Test and Verify Merge Fields, pick a user, pick an oppty and you should see a html preview as below

hello opportunity Id is : 006d0000005z1IZAAY

4
  • this is a good idea but it assumes that the Opportunity is in fact the relatedTo object when the email template is rendered by SFDC. If the template comes out of apex, the whatId's SObject becomes relevant; similarly if the template is associated to a workflow/process, the object in context had better be an Opportunity
    – cropredy
    Commented Jun 4, 2015 at 17:52
  • @crop1645 On the email template when the OP has declared the relatedToType="Opportunity" how do you say it could be any other Id?
    – Rao
    Commented Jun 4, 2015 at 17:57
  • I've had issues in past wherein context didn't exist to the expected sobject type when the email template was invoked - depends on how the template is invoked
    – cropredy
    Commented Jun 4, 2015 at 18:01
  • @crop1645 When you try to use the VF template, the email template you choose on a WF is filtered based on the related to object, so we can rule out WF causing issues. Coming to sending email through an apex class, yes I do agree that setting a wrong whatId may screw up, but not sure how since I have not tested this route
    – Rao
    Commented Jun 4, 2015 at 18:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .