You need to sign in to do that
Don't have an account?
![Jeff_Rogers.ax1383 Jeff_Rogers.ax1383](https://dfc-org-production.my.site.com/img/userprofile/default_profile_45_v2.png)
Creating a Visualforce Email Template to Display fields from Multiple Objects
I have 3 different objects that I want to display data from in anemail template: Case -> Case Product -> Problem
I want to send the email from the case page and want to display a table of Case Products and associated Problems.
Is this possible? If so, what would be the plan of attack?
I would think I'd need a component in the visualforce email template that would display data aggregated via a wrapper class.
I'm able to get this to work on a standard visualforce page with a commandlink to initiate a wrapper controller method that compiles the data for me (see the code below), but I don't know how to initiate that action through visualforce within an email template. Suggestions?
Thanks!
Visualforce Page - "TestPage" <apex:page title="Wrapper Demo" controller="wrapperCON" tabStyle="Case"> <apex:sectionHeader title="Wrapper Demo"/> <apex:form > <apex:pageBlock title="Setup"> <apex:pageBlockButtons location="top"> <apex:commandLink action="{!buildwrapper}"> <apex:param name="caseId" value="500Q0000003woSF"/> <apex:commandbutton value="Demo" /> </apex:commandLink> </apex:pageBlockButtons> </apex:pageBlock> <apex:pageBlock > <apex:repeat value="{!wrapout}" var="w"> <hr/> <apex:outputText value="{!w.caseProd.name}" /> <br/> <apex:repeat value="{!w.problems}" var="wo"> Problems: <apex:outputText value="{!wo.Prob.name}" /> <br/> </apex:repeat> </apex:repeat> </apex:pageBlock> </apex:form> </apex:page>
//APEX CONTROLLER public class wrapperCON { private List<Case_Product__c> tempCaseProd = new List<Case_Product__c>(); private Map<ID,List<Problem__C>> CaseProdProbMAP = new Map<ID,List<Problem__c>>(); private Set<ID> CaseProdIds = new Set<ID>();//case product ids to get problems from public List<wrapper> wrapout {get; set;} //constructor public wrapperCON(){ wrapout = new List<wrapper>(); } //wrapper 1 class wrapper{ public Case_Product__c caseProd {get; set;} //This is a list of other wrappers that is nested in the first list public List<wrapper2> problems {get; set;} public wrapper(){ if(caseProd==null){caseProd = new Case_Product__c();}//initialize the case product holder if(problems==null){problems = new List<wrapper2>();}//initialize the wrapper listholder } } //wrapper 2 - the sub-wrapper class wrapper2{ public Problem__c Prob {get; set;} //public List<Product2> oppprods {get; set;} /*public wrapper2(){ if(Opp==null){Opp = new Opportunity();}//initialize the Opportunity holder if(oppprods==null){oppprods = new List<Product2>();}//initialize the product2 holder }*/ } //This is the "Run Demo" Button on our VF page public PageReference buildwrapper() { String caseId = ApexPages.currentPage().getParameters().get('caseId');//'500Q0000003woSF'; String queryString = 'select id,name from Case_Product__c where case__c IN (\'' + caseId + '\')'; tempCaseProd = database.query(queryString); system.debug(tempCaseProd); for(Case_Product__c cp:tempCaseProd){CaseProdIds.add(cp.id);} for(Problem__c p:[select id,name,case_product__c from Problem__c where Case_Product__c=:CaseProdIds]){ if(CaseProdProbMap.containsKey(p.case_product__c)){ CaseProdProbMap.get(p.case_product__c).add(p);//adds problems for this case product to the problems list in the map }else{ CaseProdProbMap.put(p.case_product__c,new List<Problem__C>{p});//adds new problem list for this case product to the map } } for(Case_Product__c cp2:tempCaseProd){ wrapper tmpwrapper = new wrapper(); tmpwrapper.caseProd=cp2; List<wrapper2> t2 = new List<wrapper2>(); for(Problem__c pp:CaseProdProbMap.get(cp2.id)){ wrapper2 twrap2 = new wrapper2(); twrap2.Prob=pp; t2.add(twrap2); } tmpwrapper.problems=t2; wrapout.add(tmpwrapper); } return null; } }
You indeed need component & controller behine it.
In those cases that I need data from several objects I would rather center them in
one components, instead of creating component for each object.
you can do controller like this:
private Producy__c product =new Prodeuct();
private List<Case_Product__c> tempCaseProd = new List<Case_Product__c>();
private Map<ID,List<Problem__C>> CaseProdProbMAP = new Map<ID,List<Problem__c>>();
private String dummy='';
public getDummy()
{
//code for initialize all data
//1.product
//2.case_product list
//3.case_product_problem map
return dummy;
}
public Producy__c getProduct()
{
return product;
}
public List<Case_Product__c> getTempCaseProd()
{
return tempCaseProd ;
}
public Map<ID,List<Problem__C>> getCaseProdProbMap()
{
retrurn CaseProdProbMAP ;
}
After that in compoent call first the dummy variable.
And then call all the other objects.
something like:
{!dummy}
<apex:repeat value="{!tempCaseProd}" var="caseProd" id="caseID">
<apex:outputText value="{!caseProd.name}" /> <br/>
</apex:repeat>