+ Start a Discussion
BrandiTBrandiT 

Modify Apex Class using sObject to work for specific object

I downloaded an app called Attachment Viewer that creates a Visualforce component to display images attached to a record.  The apex class uses a generic sObject so that it can be used on any any object by just modifying the VF page.

 

Our contacts have a lookup relationship to a custom object called Business Cards (contacts are the detail side of the relationship).

 

I would like to modify this code to look for attachments on the contacts business card parent record and display them on teh contact page, but I've never used generic sObjects in code before and am not sure how to modify it.

 

Basically the class should look for attachments where Parent in in :contact.business_card__c.id.  I tried to add this with no luck.

 

Here is the code I'm trying to modify.  Any idea how I can get this to work?

 

 

 

public class ImageViewController
{
    private final SObject so;
    private List<Photo> myPhotos = new List<Photo> ();
    
    public ImageViewController (ApexPages.StandardController controller)
    {
        this.so = controller.getRecord ();
        fetchPhotos ();
    }
    public class Photo
    {
        String id;
        String url;
        String name;
        
        public Photo (String ipId, String ipName)
        {
            id   = ipId;
            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.
            name = ipName;
        }
        
        public String getId ()
        {
            return id;
        }
        
        public String getUrl ()
        {
            return url;
        }
        
        public String getName ()
        {
            return name;
        }
    }
    private void fetchPhotos ()
    {
        myPhotos.clear ();  // Empty list
        
        for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :so.Id])
        {
           // if (a.ContentType.startsWith ('image/'))  
            // Only add images to the list, ignore all other types
            {
                myPhotos.add (new Photo (a.Id, a.Name));
            }
        }
    }
                                   
    public List<Photo> getPhotos ()
    {
        return myPhotos;
    }             
}

 

 

Thanks you!!

Best Answer chosen by Admin (Salesforce Developers) 
BrandiTBrandiT

Nevermind, I got it to work!

 

Here's my final code:

 

 

public class ImageViewController_BC
{
    private Contact c;
    private List<Photo> myPhotos = new List<Photo> ();
    
    public ImageViewController_BC (ApexPages.StandardController controller)
    {
        this.c = (contact)controller.getRecord ();
        c = [SELECT Id, Business_Card__c, Business_Card__r.id FROM Contact];
        
        fetchPhotos ();
    }
    public class Photo
    {
        String id;
        String url;
        String name;
        
        public Photo (String ipId, String ipName)
        {
            id   = ipId;
            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.
            name = ipName;
        }
        
        public String getId ()
        {
            return id;
        }
        
        public String getUrl ()
        {
            return url;
        }
        
        public String getName ()
        {
            return name;
        }
    }
    private void fetchPhotos ()
    {
        myPhotos.clear ();  // Empty list
        
        for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :c.business_card__r.Id])
        {
           // if (a.ContentType.startsWith ('image/'))  
            // Only add images to the list, ignore all other types
            {
                myPhotos.add (new Photo (a.Id, a.Name));
            }
        }
    }
                                   
    public List<Photo> getPhotos ()
    {
        return myPhotos;
    }             
}

public class ImageViewController_BC{    private Contact c;    private List<Photo> myPhotos = new List<Photo> ();        public ImageViewController_BC (ApexPages.StandardController controller)    {        this.c = (contact)controller.getRecord ();        c = [SELECT Id, Business_Card__c, Business_Card__r.id FROM Contact];                fetchPhotos ();    }
    public class Photo    {        String id;        String url;        String name;                public Photo (String ipId, String ipName)        {            id   = ipId;            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.            name = ipName;        }                public String getId ()        {            return id;        }                public String getUrl ()        {            return url;        }                public String getName ()        {            return name;        }    }
    private void fetchPhotos ()    {        myPhotos.clear ();  // Empty list                for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :c.business_card__r.Id])        {           // if (a.ContentType.startsWith ('image/'))              // Only add images to the list, ignore all other types            {                myPhotos.add (new Photo (a.Id, a.Name));            }        }    }                                       public List<Photo> getPhotos ()    {        return myPhotos;    }             }

 

All Answers

BrandiTBrandiT

Ok well I almost got it with a few tweaks.  Only now I need to query a field on contact called Business_Card__c and I'm not sure how to do that:

 

Here is the new error message I'm getting and the revised code I'm trying to use:

 

Content cannot be displayed: SObject row was retrieved via SOQL without querying the requested field: Contact.Business_Card__r

 

 

public class ImageViewController_BC

{
    private final Contact c;
    private List<Photo> myPhotos = new List<Photo> ();
    
    public ImageViewController_BC (ApexPages.StandardController controller)
    {
        this.c = (contact)controller.getRecord ();
        fetchPhotos ();
    }
    public class Photo
    {
        String id;
        String url;
        String name;
        
        public Photo (String ipId, String ipName)
        {
            id   = ipId;
            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.
            name = ipName;
        }
        
        public String getId ()
        {
            return id;
        }
        
        public String getUrl ()
        {
            return url;
        }
        
        public String getName ()
        {
            return name;
        }
    }
    private void fetchPhotos ()
    {
        myPhotos.clear ();  // Empty list
        
        for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :c.business_card__r.Id])
        {
           // if (a.ContentType.startsWith ('image/'))  
            // Only add images to the list, ignore all other types
            {
                myPhotos.add (new Photo (a.Id, a.Name));
            }
        }
    }
                                   
    public List<Photo> getPhotos ()
    {
        return myPhotos;
    }             
}
Thanks again!!

 

BrandiTBrandiT

Nevermind, I got it to work!

 

Here's my final code:

 

 

public class ImageViewController_BC
{
    private Contact c;
    private List<Photo> myPhotos = new List<Photo> ();
    
    public ImageViewController_BC (ApexPages.StandardController controller)
    {
        this.c = (contact)controller.getRecord ();
        c = [SELECT Id, Business_Card__c, Business_Card__r.id FROM Contact];
        
        fetchPhotos ();
    }
    public class Photo
    {
        String id;
        String url;
        String name;
        
        public Photo (String ipId, String ipName)
        {
            id   = ipId;
            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.
            name = ipName;
        }
        
        public String getId ()
        {
            return id;
        }
        
        public String getUrl ()
        {
            return url;
        }
        
        public String getName ()
        {
            return name;
        }
    }
    private void fetchPhotos ()
    {
        myPhotos.clear ();  // Empty list
        
        for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :c.business_card__r.Id])
        {
           // if (a.ContentType.startsWith ('image/'))  
            // Only add images to the list, ignore all other types
            {
                myPhotos.add (new Photo (a.Id, a.Name));
            }
        }
    }
                                   
    public List<Photo> getPhotos ()
    {
        return myPhotos;
    }             
}

public class ImageViewController_BC{    private Contact c;    private List<Photo> myPhotos = new List<Photo> ();        public ImageViewController_BC (ApexPages.StandardController controller)    {        this.c = (contact)controller.getRecord ();        c = [SELECT Id, Business_Card__c, Business_Card__r.id FROM Contact];                fetchPhotos ();    }
    public class Photo    {        String id;        String url;        String name;                public Photo (String ipId, String ipName)        {            id   = ipId;            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.            name = ipName;        }                public String getId ()        {            return id;        }                public String getUrl ()        {            return url;        }                public String getName ()        {            return name;        }    }
    private void fetchPhotos ()    {        myPhotos.clear ();  // Empty list                for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :c.business_card__r.Id])        {           // if (a.ContentType.startsWith ('image/'))              // Only add images to the list, ignore all other types            {                myPhotos.add (new Photo (a.Id, a.Name));            }        }    }                                       public List<Photo> getPhotos ()    {        return myPhotos;    }             }

 

This was selected as the best answer
Scott M - SFDC FanScott M - SFDC Fan

Coming back to this after a long while, as my boss wants this working in the cases too. I am pulling my hair out here.

 

This is my code.

 

public class ImageViewController
{
    private final SObject so;
    private List<Photo> myPhotos = new List<Photo> ();
    
    
    public ImageViewController (ApexPages.StandardController controller)
    {
        this.so = controller.getRecord ();
        fetchPhotos ();
    }

    public class Photo
    {
        String id;
        String url;
        String name;
        
        public Photo (String ipId, String ipName)
        {
            id   = ipId;
            url  = '/servlet/servlet.FileDownload?file=' + id;  // This is the standard SFDC manner to "download" attachments.
            name = ipName;
        }
        
        public String getId ()
        {
            return id;
        }
        
        public String getUrl ()
        {
            return url;
        }
        
        public String getName ()
        {
            return name;
        }
        
    }

    private void fetchPhotos ()
    {
        myPhotos.clear ();  // Empty list
        
        for (Attachment a : [Select Id, Name, ContentType From Attachment Where ParentId = :so.Id])
        {   
            if (!a.Name.endsWith ('tif')) // Don't let TIFs get compared, as these can't be viewed by the viewer.
            {  

                if (a.ContentType.contains ('image/'))  // Only add images except TIFs to the list, ignore all other types
                {
                    myPhotos.add (new Photo (a.Id, a.Name));
                }
             
            }
        }
            
    }
                               
    public List<Photo> getPhotos ()
    {
        return myPhotos;
    }         
        
}

 

This is the page calling it.

 

<apex:page standardController="Case" extensions="ImageViewController" showHeader="false" sidebar="false" standardStylesheets="false">
    
    <apex:styleSheet value="{!URLFOR($Resource.picbox,'picbox.css')}"/> 
    <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"/> 
    <apex:includeScript value="{!URLFOR($Resource.picbox,'picbox.js')}"/>
    
    
          <script>
               if (!/android|iphone|ipod|series60|symbian|windows ce|blackberry/i.test(navigator.userAgent)) {
                    jQuery(function($) {
                        $("a[rel^='lightbox']").picbox({/* Put custom options here */}, null, function(el) {
                        return (this == el) || ((this.rel.length > 8) && (this.rel == el.rel));
                        });
                    });
               }
               
         </script>        
  

          <apex:repeat value="{!Photos}" var="p">
                <a rel="lightbox-viewer" href="{!p.url}"  title="{!p.name}">
                     <img width="150" height="150" alt="{!p.name}" src="{!p.url}" title="{!p.name}" />
                </a>
              
           </apex:repeat>

      
</apex:page>

 

It works like a charm in our sandbox for both the case object and the custom objects.

 

The same controller extension works for a custom object on our life system.

 

Yet it comes up with

 

Attempt to de-reference a null object

 

on line 52, when I try to add this for a case on the live system. I can't for the life of me figure this out.

 

Heeeelllllllp!:)

 

Scott