Visual-Force email template

The top level Element must be <messaging:emailTemplate />. The attribute subject should be set it is the email-subject. It may have the Attribute recipientType and relatedToType.

The Visual-Force email template layout for "Subject" looks somewhat like this:

<messaging:emailTemplate subject="Subject" relatedToType="Opportunity">
        <messaging:plainTextEmailBody >
                ...
                <c:Greeting AccountId="{!relatedTo.AccountId}" />
                ...
                <c:GFundsProduct OpportunityId="{!relatedTo.Id}"/>
                ...
                <c:GFundsProductFiles OpportunityId="{!relatedTo.Id}"/>
                ..
                <c:Owner OwnerId="{!relatedTo.OwnerId}"/>
                ...
        </messaging:plainTextEmailBody> 
        <messaging:htmlEmailBody >
                ...
                <c:Greeting AccountId="{!relatedTo.AccountId}" />
                ...
                <c:GFundsProduct OpportunityId="{!relatedTo.Id}"/>
                ...
                <c:GFundsProductFiles OpportunityId="{!relatedTo.Id}"/>
                ..
                <c:Owner OwnerId="{!relatedTo.OwnerId}"/>
                ...
        </messaging:htmlEmailBody>
</messaging:emailTemplate>

The recipientType may be Lead, Contact or User:

<messaging:emailTemplate subject="Subject" recipientType="Contact">
        <messaging:plainTextEmailBody >
                ...
                <c:RecipientData RecipientId="{!recipient.Id}" />
                ...
        </messaging:plainTextEmailBody> 
</messaging:emailTemplate>

APEX Component

The APEX component has the attribute id which has the the same name as the <c:GFundsProductFiles in the Visual-Force email template. The attribute controller tells the APEX component which class is responsible. Next the <apex:attribute assignTo="{!OpportunityId}" calls the controller method:

public Id ProductId
{
        get;set;
}

The <apex:repeat value="{!ProductfurtherDocuments}" is a loop iterating over the List gained by the controller method getProductfurtherDocuments. Each List element of type SObject Productfiles__c in each loop step is assigned to var="further". You can access a field by e.g. calling {!further.Name} which would get you the Productfiles__c.Name:

<apex:component id="GFundsProductFiles" controller="AutoResponderComponentController" allowDML="true" access="global">
        <apex:attribute name="OpportunityId" type="Id" description="Opportunity Id" assignTo="{!OpportunityId}"/>
        <ul>
        <apex:repeat value="{!ProductfurtherDocuments}" var="further" id="furtherRepeat">
                <li><a href="http://pdf.fondsvermittlung24.de/{!further.Filename__c}">{!further.Name}</a></li>
        </apex:repeat>
        </ul>
        <p><font size="2">Im Folgenden  finden Sie alle Beitrittsunterlagen:</font></p>
        <ul>
        <apex:repeat value="{!ProductfilesSubscriptionDocuments}" var="subscription" id="subscriptionRepeat">
                <li><a href="http://pdf.fondsvermittlung24.de/{!subscription.Filename__c}">{!subscription.Name}</a></li>
        </apex:repeat>
        </ul>
</apex:component>

Apex Class

Now the actual implementation of the controller class AutoResponderComponentController. Here an example to get the latest SObject Product2 from an Opportunity SObject. In our work-flow we only have on product per opportunity. A Trigger prevents adding another product to an opportunity.

public class AutoResponderComponentController
{
    public Id OpportunityId
    {
        get;set;
    }
    ...
    private Id aquirePriceBookEntryId()
    {
        OpportunityLineItem oli = [SELECT ole.PricebookEntryId 
                                        FROM OpportunityLineItem ole 
                                        WHERE ole.OpportunityId =: OpportunityId
                                        ORDER BY ole.CreatedDate DESC
                                        LIMIT 1];
        Id priceBookEntryId = oli.PricebookEntryId;
        return priceBookEntryId;
    }
 
    private Id aquireProduct2Id(Id priceBookEntryId)
    {
        PricebookEntry pe = [SELECT pe.Product2Id
                                FROM PricebookEntry pe 
                                WHERE pe.Id =: priceBookEntryId
                                LIMIT 1];
        Id product2Id = pe.Product2Id;
        return product2Id;
    }
 
    public String getProductNameByOpportunityId()
    {
        Id priceBookEntryId = aquirePriceBookEntryId();
        Id product2Id = aquireProduct2Id(priceBookEntryId);
        Product2 product2 = [SELECT p.Name FROM Product2 p WHERE p.Id =: product2Id LIMIT 1];
        String name = product2.Name;
        return name;
    }
    ...
}

Weblinks