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
fer_farfer_far 

Custom components with email templates

Hi,

 

Is it possible to send emails with visualforce templates using custom components?

 

I have written an Apex controller, a custom component and a visualforce email template. In the template I'm using {!relatedTo} to pass a custom object to the component, but it seems to fail when I try to send the email with a SingleEmailMessage using the template.

 

Can someone help me please?

 

Thanks in advance.

Best Answer chosen by Admin (Salesforce Developers) 
mtbclimbermtbclimber
Based on what you are indicating, you should not need a custom component with a controller for this.

All Answers

mtbclimbermtbclimber
can you describe the failure in more detail?
fer_farfer_far
Sorry, I forgot to explain the error in more detail.

The error happens when I try to preview the template after saving, the error message is "Attempt to de-reference a null object". It looks like the template cannot resolve {!relatedTo}.

The same occurs when sending the email with SingleEmailMessage.
mtbclimbermtbclimber
That's an NPE from your apex class. Does it have anymore information than "Attempt to de-reference a null object"?
Message Edited by mtbclimber on 06-06-2009 01:00 PM
fer_farfer_far

No, this is the only message shown.

I will paste the code:

The Apex controller is something like this:

 

public class sendOffer { public String url {get; set;} public BXES_Bid_and_Offers__c offer {get; set;} public sendOffer() { if (offer.FTES_Estado__c == 'XXXXX') { url = 'imageurl1'; } else { url = 'imageurl2'; } } }

 

The custom component is:

 

 

<apex:component controller="sendOffer" access="global"> <apex:attribute name="myOffer" type="BXES_Bid_and_Offers__c" assignTo="{!offer}"/> <apex:image style="position: absolute; left: 50%; top: 11%" value="{!url}"/> </apex:component>

 

 

In the template I use the component:

 

...

relatedToType="BXES_Bid_and_Offers__c" 

...

<c:sendOffer myOffer="{!relatedTo}"/>

 

 

And the email is sent from a trigger using a SingleEmailMessage object: 

 

 

BXES_Bid_and_Offers__c[] OffersNew = Trigger.new; for(BXES_Bid_and_Offers__c offer: OffersNew){ Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); String[] addresses = new String[]{}; addresses.add(offer.FTES_Customer_Service__c); addresses.add(offer.FTES_Sales_Manager__c); if (!direcciones.IsEmpty()) { email.setToAddresses(addresses); } email.setSaveAsActivity (false); email.setTemplateId('00XS0000000IY5Y'); email.setTargetObjectId(offer.OwnerId); email.setWhatId (offer.Id); Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); }

I hope this helps.

mtbclimbermtbclimber

fer_far wrote:

}

I hope this helps.


 

 

 

 

it does.  Here's your problem:

 


fer_far wrote:

 

The Apex controller is something like this:

 

public class sendOffer {

public String url {get; set;}
public BXES_Bid_and_Offers__c offer {get; set;}

public sendOffer() {

if (offer.FTES_Estado__c == 'XXXXX') {
url = 'imageurl1';
} else {
url = 'imageurl2';
}
}
}



 

 You are referring to members on the object being passed in, offer, before the setter is actually called.  The constructor is the first thing that is invoked so offer is still null at that point and referencing .FTES_Estado__c on the null offer throws the error.

 

In most cases we show line/column numbers for this type of error - it seems we missed that in the Visualforce email template UI/situation.  I'll make sure the owner for this area is informed.  

 

To fix this for your specific case based on what I see here, I recommend eliminating the url property and replacing it  with a getUrl method. In this case your controller would look like this:

 

 

public class sendOffer { public BXES_Bid_and_Offers__c offer {get; set;} public String getUrl() { return offer.FTES_Estado__c == 'XXXXX' ? 'imageurl1' : 'imageurl2'; } }

 

 

 

 

fer_farfer_far

Thank you very much for your help.

 

I tried your fix typing the following in my custom component (after ):

 

value="{!getURL()}"

 

or

 

value="{!getURL}

 

But both of them fail when saving. The errors shown are "getURL function unknown" and "getURL property unknown". It looks like the component does not recognize getURL method from the class.

 


 

 

 

mtbclimbermtbclimber

Did I say to make any changes to your component? :smileywink:

 

 

Your binding should remain {!url} (i.e. drop the 'get'). 

fer_farfer_far

Thanks again, I thought that was the way ...

 

Now, when selecting the template to send an email the error is: SObject row was retrieved via SOQL without querying the requested field: BXES_Bid_and_Offers__c.FTES_Estado__c

mtbclimbermtbclimber

You need to seed your relatedTo object with a reference you need in the controller, or query in your controller for the data it needs but taking a step back, do you need a controller here at all?

 

This logic can be built into the template:

 

<apex:image style="position: absolute; left: 50%; top: 11%" value="{!IF(offer.FTES_Estado__c = 'XXXXX','imageurl1','imageurl2')}"/>

 

 

 

Message Edited by mtbclimber on 06-08-2009 08:46 AM
fer_farfer_far
I have to show an image (in a PDF document) depending on the status. Therefore I only need to check the offer status and then choose the right image. Is it possible to use the following? Thanks so much.
mtbclimbermtbclimber
Based on what you are indicating, you should not need a custom component with a controller for this.
This was selected as the best answer
fer_farfer_far

Thank you very much for your help !!!

 

Finally I got it. As you said, I had no need of controllers / components. I didn't know all the possibilities that templates provide since I'm not very experienced in developing with VF.

 

Regards.