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
Nicholas LabradaNicholas Labrada 

apex:repeat in which my starting point is a child object to a parent object and I want to access another set of child objects related to that parent

Hi,

I'd like some help trying to figure out the following. I am trying to build a visualforce email template that starts at object "case". "case" is a child object to parent object "Quote". I am attempting to do an <apex:repeat> in which I grab another child object "quote line items" which is child object to parent object "Quote". Is this possible? Here is my code:
 
<messaging:emailTemplate subject="Quote-to-Order Submission Received:{!relatedTo.Account}" recipientType="User" relatedToType="Case">
<messaging:htmlEmailBody>
<html>
    <body>
        <p>Dear {!relatedTo.Created_By_Quote__c},</p>
        <p>Thank you for submitting your quote-to-order request for Account Name: {!relatedTo.Account}. Your Case# is {!relatedTo.CaseNumber}. Below are you quote details: </p>
        
        <p><table border="1" cellpadding="5">
                        <tr > 
                            <th>Line Number</th><th>Part Number</th><th>Quantity</th><th>Unit Price</th><th>Line Total</th>
                        </tr>
                        <apex:repeat var="qline" value="{!relatedTo.Quote__r}">
                            <tr>
                            </tr>
                        </apex:repeat>                 
            </table>
        </p>
        
    </body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

 
Best Answer chosen by Nicholas Labrada
Suresh Dupada pdIISuresh Dupada pdII
Hi Nicholas Labrada, 
          You can achive this with the followings.

//create apex class with name "EmailQuoteQuoteLineItemsController"

public class EmailQuoteQuoteLineItemsController{        
    public Case caseRec {set;get;}
    public Quote quoteRec {set;get;}    
    public String caseRecId{get; 
        set {
            caseRecId = value;
            init();
        }
    }    
    public void init(){
        //loading case record with RelatedToType Id assignment from visualforce component attribute
        caseRec = [Select Id, CaseNumber, Created_By_Quote__c, Account.Name, Quote__c from Case where Id=: caseRecId];
        
        //query Quote and QuoteLineItems
        if(caseRec.Quote__c!=null){
            quoteRec  = [Select Id, Name, (Select Id, Name, UnitPrice, TotalPrice, Quantity from QuoteLineItems) from Quote where Id=:caseRec.Quote__c];
        }
    }
}

//Create visualforce component with name "EmailQuoteQuoteLineItems"
<apex:component access="global" controller="EmailQuoteQuoteLineItemsController">

<apex:attribute type="String" name="ObjectId" description="Case Record Id" assignTo="{!caseRecId}"/>
    <html>
        <body>
            <p>Dear {!caseRec.Created_By_Quote__c},</p>
            <p>Thank you for submitting your quote-to-order request for Account Name: {!caseRec.Account.Name}. Your Case# is {!caseRec.CaseNumber}. Below are you quote details: </p>
            
            <p><table border="1" cellpadding="5">
                            <tr > 
                                <th>Line Number</th><th>Part Number</th><th>Quantity</th><th>Unit Price</th><th>Line Total</th>
                            </tr>
                            <apex:repeat var="qline" value="{!quoteRec.QuoteLineItems}">
                                <tr>
                                    <td>your line number api</td> <!- change this to your api -->
                                    <td>your partnumber api</td> <!- change this to your api -->
                                    <td>qline.Quantity</td>
                                    <td>qline.UnitPrice</td>
                                    <td>qline.TotalPrice</td>
                                </tr>
                            </apex:repeat>                 
                </table>
            </p>
            
        </body>
    </html>
</apex:component>

//Finally replace your  visualforce email template body with below code.

<messaging:emailTemplate subject="Quote-to-Order Submission Received:{!relatedTo.Account}"  recipientType="User" relatedToType="Case">
    <messaging:htmlEmailBody >
        <c:EmailQuoteQuoteLineItems caseRecId="{!relatedTo.Id}"></c:EmailQuoteQuoteLineItems>
    </messaging:htmlEmailBody>
</messaging:emailTemplate>

 

All Answers

Suresh Dupada pdIISuresh Dupada pdII
Hi Nicholas Labrada, 
          You can achive this with the followings.

//create apex class with name "EmailQuoteQuoteLineItemsController"

public class EmailQuoteQuoteLineItemsController{        
    public Case caseRec {set;get;}
    public Quote quoteRec {set;get;}    
    public String caseRecId{get; 
        set {
            caseRecId = value;
            init();
        }
    }    
    public void init(){
        //loading case record with RelatedToType Id assignment from visualforce component attribute
        caseRec = [Select Id, CaseNumber, Created_By_Quote__c, Account.Name, Quote__c from Case where Id=: caseRecId];
        
        //query Quote and QuoteLineItems
        if(caseRec.Quote__c!=null){
            quoteRec  = [Select Id, Name, (Select Id, Name, UnitPrice, TotalPrice, Quantity from QuoteLineItems) from Quote where Id=:caseRec.Quote__c];
        }
    }
}

//Create visualforce component with name "EmailQuoteQuoteLineItems"
<apex:component access="global" controller="EmailQuoteQuoteLineItemsController">

<apex:attribute type="String" name="ObjectId" description="Case Record Id" assignTo="{!caseRecId}"/>
    <html>
        <body>
            <p>Dear {!caseRec.Created_By_Quote__c},</p>
            <p>Thank you for submitting your quote-to-order request for Account Name: {!caseRec.Account.Name}. Your Case# is {!caseRec.CaseNumber}. Below are you quote details: </p>
            
            <p><table border="1" cellpadding="5">
                            <tr > 
                                <th>Line Number</th><th>Part Number</th><th>Quantity</th><th>Unit Price</th><th>Line Total</th>
                            </tr>
                            <apex:repeat var="qline" value="{!quoteRec.QuoteLineItems}">
                                <tr>
                                    <td>your line number api</td> <!- change this to your api -->
                                    <td>your partnumber api</td> <!- change this to your api -->
                                    <td>qline.Quantity</td>
                                    <td>qline.UnitPrice</td>
                                    <td>qline.TotalPrice</td>
                                </tr>
                            </apex:repeat>                 
                </table>
            </p>
            
        </body>
    </html>
</apex:component>

//Finally replace your  visualforce email template body with below code.

<messaging:emailTemplate subject="Quote-to-Order Submission Received:{!relatedTo.Account}"  recipientType="User" relatedToType="Case">
    <messaging:htmlEmailBody >
        <c:EmailQuoteQuoteLineItems caseRecId="{!relatedTo.Id}"></c:EmailQuoteQuoteLineItems>
    </messaging:htmlEmailBody>
</messaging:emailTemplate>

 
This was selected as the best answer
Nicholas LabradaNicholas Labrada
Hello,

First, thank you so much for the help.

I am about 90% of the way there and I am getting an error on the email template. It is telling me that the caseRecId is an unsupported attribute.User-added image
Nicholas LabradaNicholas Labrada
Just so you can see it, ill provide the class and controller I created. I had to modify slightly as you had recommended:
 
public class EmailQuoteQuoteLineItemsController{        
    public Case caseRec {set;get;}
    public Quote quoteRec {set;get;}    
    public String caseRecId{get; 
        set {
            caseRecId = value;
            init();
        }
    }    
    public void init(){
        //loading case record with RelatedToType Id assignment from visualforce component attribute
        caseRec = [Select Id, CaseNumber, Created_By_Quote__c, Account.Name, Quote__c from Case where Id=: caseRecId];
        
        //query Quote and QuoteLineItems
        if(caseRec.Quote__c!=null){
            quoteRec  = [Select Id, Name, (Select Id, LineNumber, Product_Name__c, UnitPrice, Quantity, TotalPrice from QuoteLineItems) from Quote where Id=:caseRec.Quote__c];
        }
    }
}
 
<apex:component access="global" controller="EmailQuoteQuoteLineItemsController">

<apex:attribute type="String" name="ObjectId" description="Case Record Id" assignTo="{!caseRecId}"/>
    <html>
        <body>
            <p>Dear {!caseRec.Created_By_Quote__c},</p>
            <p>Thank you for submitting your quote-to-order request for Account Name: {!caseRec.Account.Name}. Your Case# is {!caseRec.CaseNumber}. Below are you quote details: </p>
            
            <p><table border="1" cellpadding="5">
                            <tr > 
                                <th>Line Number</th><th>Part Number</th><th>Quantity</th><th>Unit Price</th><th>Line Total</th>
                            </tr>
                            <apex:repeat var="qline" value="{!quoteRec.QuoteLineItems}">
                                <tr>
                                    <td>qline.LineNumber</td>
                                    <td>qline.Product_Name__c</td>
                                    <td>qline.Quantity</td>
                                    <td>qline.UnitPrice</td>
                                    <td>qline.TotalPrice</td>
                                </tr>
                            </apex:repeat>                 
                </table>
            </p>
            
        </body>
    </html>
</apex:component>

 
Suresh Dupada pdIISuresh Dupada pdII

Sorry small mistake

 <c:EmailQuoteQuoteLineItems caseRecId="{!relatedTo.Id}"></c:EmailQuoteQuoteLineItems>  change the attribute name from caseRecId to ObjectId (simply replace with below line in email template body)
 <c:EmailQuoteQuoteLineItems ObjectId="{!relatedTo.Id}"></c:EmailQuoteQuoteLineItems>

Nicholas LabradaNicholas Labrada
Awesome! Thank you so much.

I had to make a quick tweak to the controller as well, the apex:repeat was missing the {! }. You are the best! Thank you so much!
Nicholas LabradaNicholas Labrada
Suresh,

Below I am trying to center individual columns within the table that you help me build. Would you be able to share how I would do that?
 
<p><table border="1" cellpadding="3" align="center">
                            <tr > 
                                <th>Part Number</th><th>Quantity</th><th>Unit Price</th><th>Line Total</th>
                            </tr>
                            <apex:repeat var="qline" value="{!quoteRec.QuoteLineItems}">
                                <tr>
                                    <td>{!qline.Product2.Name}</td>
                                    <td><apex:outputText value="{0, number, integer}"><apex:param value="{!qline.Quantity}"/></apex:outputText></td>
                                    <td><apex:outputText value="{0, number, currency}"><apex:param value="{!qline.UnitPrice}"/></apex:outputText></td>
                                    <td><apex:outputText value="{0, number, currency}"><apex:param value="{!qline.TotalPrice}"/></apex:outputText></td>
                                </tr>
                            </apex:repeat>                 
                </table>
            </p>

 
Suresh Dupada pdIISuresh Dupada pdII

can you try below link, you can check attribute (align) values with (left/right/center)

https://www.w3schools.com/tags/att_td_align.asp

if above link not works, please share you screenshot, so I will give you some suggestions. (before that you can do with inspect element for column and change element style).

Note: in your case, Inline style only works for you.