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
kevin Carotherskevin Carothers 

Error occurred trying to load the template for preview: VF Component

Hi All,

I'm trying to use a component in a VF email template.
The Component looks like this;
<apex:component controller="findDetailData" access="global">
  <apex:attribute name="xstrOpptyId" description="opportunity ID" type="String" assignTo="{!strOptID}"/>
  <table>
  <tr>
   <td>Name</td>
   <td>Quantity</td>
   <td>UoM</td>
   <td>NRC</td>
   <td>Price</td>
   <td>Variance</td>
   <td>MRC</td>
   <td>Waived</td>
  </tr>
  <apex:repeat var="opp" value="{!opptyLines}">
     <td>{!opp.PriceBookEntry.name}</td>
     <td align="right">{!ROUND(opp.Quantity,0)}</td>
     <td align="left">{!opp.UoM__c}</td>
     <td align="right">{!ROUND(opp.NRC__c,0)}</td>
     <td align="right">{!ROUND(opp.Variance__c,0)}</td>
     <td align="right">{!ROUND(opp.TotalPrice,0)}</td>
     <td align="left">{!opp.Waived__c}</td>
  </apex:repeat>
  </table>  
</apex:component>

And the controller is this;
public class findDetailData {
    public  List<OpportunityLineItem> opptyLines = new List<OpportunityLineItem>();
    public String strOptID{get;set;}

    public findDetailData() {
        
        Opportunity lo = [SELECT Amount, Id, Name, (SELECT Quantity, NRC__c,
        PriceBookEntry.UnitPrice, PricebookEntry.Name,
        Variance__c, TotalPrice, Waived__c FROM OpportunityLineItems)
        FROM Opportunity
        WHERE Id =  :strOptID LIMIT 1];
        
        //System.debug('lo.size(): ' + lo.size());
        OpportunityLineItem ox = new OpportunityLineItem(Quantity=1,UoM__c='', NRC__c=0,TotalPrice=0,Waived__c=false);
        
        opptyLines = lo.OpportunityLineItems;
        }

    public List<OpportunityLineItem> getopptyLines() {
        return opptyLines;
        }
    }

....And when I onsert it on the page, I'm declaring it like this;
<c:findDetailData xstrOpptyId="{!relatedTo.OpportinityId__c}"/>

....But I keep getting the error  "Error occurred trying to load the template for preview: List has no rows for assignment to SObject. Please try editing your markup to correct the problem"



 
Tejpal KumawatTejpal Kumawat

You're getting "System.QueryException: List has no rows for assignment to SObject" because the following query is not returning any records:
 
Opportunity lo = [SELECT Amount, Id, Name, (SELECT Quantity, NRC__c,
        PriceBookEntry.UnitPrice, PricebookEntry.Name,
        Variance__c, TotalPrice, Waived__c FROM OpportunityLineItems)
        FROM Opportunity
        WHERE Id =  :strOptID LIMIT 1];

Use it by taking list of opportunity and check size if greater than 0 :
 
list<Opportunity> lo = [SELECT Amount, Id, Name, (SELECT Quantity, NRC__c,
        PriceBookEntry.UnitPrice, PricebookEntry.Name,
        Variance__c, TotalPrice, Waived__c FROM OpportunityLineItems)
        FROM Opportunity
        WHERE Id =  :strOptID LIMIT 1];


If this answers your question then hit Like and mark it as solution!
 
kevin Carotherskevin Carothers
Hi Tejpal!
Thanks for the reply and suggestion.  I gave you the thumbs up for your input.

The solution I finally found that works is somewhat odd (to me), and I'm not sure if it's the best/optimal resolution to the issue, but the problem seems to be rooted with the Opportunity ID in the component controller being null.

So - when during preview if the template I check for an opportunity that is "guaranteed" to be there (ie; "test") it seems to work.  The re-write of the component controller is this;
 
public class findDetailData {
    public  List<OpportunityLineItem> opptyLines = new List<OpportunityLineItem>();
    public String strOptID{get;set;}
    public OpportunityLineItem ox = new OpportunityLineItem(Quantity=1,UoM__c='', NRC__c=0,TotalPrice=0,Waived__c=false);
    
    public findDetailData () {
        System.debug('Constructing findDetailData : ' + strOptID);
        }
    
    public void queryDetailData() {
        if(strOptID == null) {       // <=====  ADDED FOR PREVIEW MODE
            Opportunity tempOppty = [SELECT Id FROM Opportunity  WHERE Name LIKE '%Test%' LIMIT 1];
            strOptID = tempOppty.Id;
			}
        
        Opportunity lo;    
        lo = [SELECT Amount, Id, Name, (SELECT Quantity, NRC__c,
        PriceBookEntry.UnitPrice, PricebookEntry.Name, UoM__c,
        Variance__c, TotalPrice, Waived__c FROM OpportunityLineItems)
        FROM Opportunity  WHERE Id =  :strOptID LIMIT 1];
        
        System.debug('opptyLines.size(): ' + opptyLines.size());        
        
 	    For(OpportunityLineItem oli :lo.OpportunityLineItems) {
		   opptyLines.add(oli);
		   }
        }
    public void putstrOptID(String xs)   {
        strOptID = xs;
        System.debug('opptyLines. ID: ' + strOptID);
        }
        
    public List<OpportunityLineItem> getopptyLines() {
        System.debug('opptyLines(1) ID: ' + strOptID);
        queryDetailData();
        return opptyLines;
        }
    }

...Then all works fine.   I guess my question to the community is, is there a better way to do this?   this depends on a "Test" opportunity existing in sandbox and production - this is a dependency that I don't like.    Thanks again fir any help.