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
Vinnie BVinnie B 

Would like to put an 'Add Attachment' button onto a VF page on the contact page layout

We're trying to get rid of the Notes and Attachments section of the Contact page layout since it's not customizable.  However, we need a new "Attachments" section to replicate the attachments functionality of that related list.

 

I figured out how to create a VF page which shows the Attachments for the contact and have put that on the page layout.  I am stuck at adding an "Add Attachment" button on this page.

 

I think it's down to just writing a controller that will open the standard add attachment page and linking that attachment to the contact.  Any help here would be appreciated.

 

Note that I'm not trying to do anything with the file contents. I just want the standard Add Attachment functionality that you see in the default Notes and Attachments related list.

 

I'm fairly new to VF so this is hopefully something that's pretty simple.  :)

 

THANKS!!

Best Answer chosen by Admin (Salesforce Developers) 
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Try this but you might have to pretty it up a bit:

 

<apex:page standardController="Contact" extensions="ContactExt">


<apex:form >
<apex:pageBlock title="Attachment" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton value="Save"
action="{!save}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection collapsible="false"
columns="1" >
<apex:inputHidden value="{!Contact.Name}"/>
<apex:outputText value="Attachment: "/><apex:inputFile value="{!bl}" filename="{!fileName}"/><br/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
<apex:relatedList subject="{!account}" title="Attachments"
list="NotesAndAttachments" >   
</apex:relatedList>
</apex:form>
</apex:page>

 and this is the extension:

 

public class ContactExtension{
    public Contact webContact{get;set;}
    public ContactExtension(ApexPages.StandardController stdController){
    this.webContact = (Contact)stdController.getRecord();
    //attach = new Attachment();
    }
    
    public Attachment attach = new Attachment();
    public Blob bl {get; set;} 
    public String contentType {get; set;} 
    public String fileName {get; set;}
    
    public PageReference save(){
        attach.OwnerId = UserInfo.getUserId();
        attach.ParentId = webContact.Id;
        attach.Name = fileName;
        attach.Body = bl;
        attach.ContentType = contentType;
        
        insert attach;
        /*try {
            insert attach;
        } catch (DMLException e) {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));
        return null;
        } finally {
        attach = new Attachment(); 
        }*/
        
        PageReference p= new PageReference('/apex/VFpage');
        p.setRedirect(true);
        
        return p;
    }
}

 Please mark as solution and send kudos if the answer helps

 

Mikie

All Answers

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

I have recently done almost exactly this. I dont even think that you need an extension or controller, just use the normal salesforce one. Try this:

 

<apex:relatedList subject="{!contacts}" title="Attachments"
list="NotesAndAttachments" >   
</apex:relatedList>

 then at the top of the VF page add this:  

 

<style>
input[name=newNote] {
    display: none;
}
</style>

 This will paste the notes and attachments related list onto your VF page, except that rather than being called notes and attachments, it will now be called just attachments. The second bit of code will remove the 'new note' button. Essentially the notes and attachments related list...will become an attachments list.

 

If this is not what you wanted and you want to keep the list but have a different method of uploading attachments I have also done this recently as well. let me know.

If this is what you wanted send kudos and accept as answer. 

 

Mikie

Vinnie BVinnie B

THANKS for your help!  I think your solution will work.  However, I can't see how to put that VF code into a complete VF page.  I keep getting complaints aobut not finding the "contacts" property.  Could you please post the entire code for the VF page?

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Post your VF page and I will add the code to your page. The rest of my code will not help you at all.

 

Remember to mark my answer as the solution and send kudos if my posts helped you.

Vinnie BVinnie B

This is what I came up with based on your code.  However, the Add Attachment button, or opening the attachment itself, opens a window inside the VF Page as opposed to opening a new window.

 

<apex:page standardController="Contact">
<style>
input[name=newNote] {
    display: none;
}
</style>
<apex:relatedList title="Attachments" list="CombinedAttachments" >   
</apex:relatedList>
</apex:page>

 

Here's the VF page that I came up with.  This opens up the link to the attachment in its own window.  The button that I've added below references a controller as it should.  However, I could not figure out how to code that controller to bring up the standard Add Attachment window, referencing the contact in question, in its own window.

 

THANKS again!!

 

<apex:page standardController="Contact" extensions="Attach2Contact">
<apex:form >

<apex:pageblock title="Attachments Only - No Notes" >
                <apex:commandButton action="{!AddAttachment}" value="Add Attachment" id="AddAttachButton"/>
                <apex:pageBlockTable Value="{!Contact.Attachments}" var="item" columns="4" >
                                                                 
                                <apex:column HeaderValue="Name"  >    
                                                <apex:outputLink value="/{!item.id}" id="the_link" rendered="{!NOT(Contains(item.Name,'IN_'))}" target="_top">
                                                  <apex:outputField value="{!item.Name}" /> 
                                                </apex:outputLink>                                </apex:column>
                                <apex:column HeaderValue="Size" >
                                                <apex:outputField value="{!item.BodyLength }" /> 
                                                               
                                </apex:column>                                <apex:column HeaderValue="Last Modified Date" >
                                                <apex:outputField value="{!item.LastModifiedDate }" /> 
                    </apex:column>
                                <apex:column HeaderValue="Created By" >
                                                <apex:outputField value="{!item.Createdbyid }" /> 
                                                               
                                </apex:column>
                                                  
                </apex:pageBlockTable>
</apex:pageblock>

</apex:form>
</apex:page>
             
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Try this but you might have to pretty it up a bit:

 

<apex:page standardController="Contact" extensions="ContactExt">


<apex:form >
<apex:pageBlock title="Attachment" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton value="Save"
action="{!save}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection collapsible="false"
columns="1" >
<apex:inputHidden value="{!Contact.Name}"/>
<apex:outputText value="Attachment: "/><apex:inputFile value="{!bl}" filename="{!fileName}"/><br/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
<apex:relatedList subject="{!account}" title="Attachments"
list="NotesAndAttachments" >   
</apex:relatedList>
</apex:form>
</apex:page>

 and this is the extension:

 

public class ContactExtension{
    public Contact webContact{get;set;}
    public ContactExtension(ApexPages.StandardController stdController){
    this.webContact = (Contact)stdController.getRecord();
    //attach = new Attachment();
    }
    
    public Attachment attach = new Attachment();
    public Blob bl {get; set;} 
    public String contentType {get; set;} 
    public String fileName {get; set;}
    
    public PageReference save(){
        attach.OwnerId = UserInfo.getUserId();
        attach.ParentId = webContact.Id;
        attach.Name = fileName;
        attach.Body = bl;
        attach.ContentType = contentType;
        
        insert attach;
        /*try {
            insert attach;
        } catch (DMLException e) {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));
        return null;
        } finally {
        attach = new Attachment(); 
        }*/
        
        PageReference p= new PageReference('/apex/VFpage');
        p.setRedirect(true);
        
        return p;
    }
}

 Please mark as solution and send kudos if the answer helps

 

Mikie

This was selected as the best answer
Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Replace VF page with your VF page url

Vinnie BVinnie B

Thanks so much!!  I will need to do some cosmetic reformatting but that's the piece of the code I couldn't figure out.

Vinnie BVinnie B

Here's the final code I came up with.  I tested it and am quite happy with how it works. I'm still a total rookie at this and would appreciate any suggested improvements.  THANKS again!!

 

I did some cosmetic changes and also:

 

 1. Changed the return page to be the page itself with the Contact ID appended to it.  When imbedded on a page layout, this makes it look just like it did before with the new attachment present.

 

 2. Put in an error message if the user tries to add a file before selecting one.  To do this I had to further append the return URL with an error flag.  The error message is shown if this flag is present.

 

One little tidbit I discovered was that the text for the inputFile button depends on your browser.  In Chrome it comes up as "Choose file".  In Firefox it's "Browse..."

 

The VF Page:

 

<apex:pageblock title="Attachments" >
   <apex:inputHidden value="{!Contact.Name}"/>
   <apex:inputFile value="{!bl}" filename="{!fileName}"/>
   <apex:commandButton value="Add Selected File" action="{!save}"/>
   <apex:outputText value="  You must first select the file!" rendered="{!showError}" />
   
   <apex:pageBlockTable Value="{!Contact.Attachments}"
       var="item" columns="4" >
     <apex:column HeaderValue="Name"  >    
       <apex:outputLink value="/{!item.id}" id="the_link"
           rendered="{!NOT(Contains(item.Name,'IN_'))}" target="_top">
         <apex:outputField value="{!item.Name}" />
       </apex:outputLink>
     </apex:column>
     <apex:column HeaderValue="Size" >
       <apex:outputField value="{!item.BodyLength }" />
     </apex:column>
     <apex:column HeaderValue="Last Modified Date" >
       <apex:outputField value="{!item.LastModifiedDate }" />
     </apex:column>
     <apex:column HeaderValue="Created By" >
       <apex:outputField value="{!item.Createdbyid }" />
     </apex:column>
   </apex:pageBlockTable>
</apex:pageblock>

</apex:form>
</apex:page>

 

The Controller:

 

public class ContactAttachmentController{
    public Contact webContact{get;set;}
    public ContactAttachmentController(ApexPages.StandardController stdController){
      this.webContact = (Contact)stdController.getRecord();
      showErrorString=ApexPages.currentPage().getParameters().get('showError');
      if (showErrorString == 'TRUE') {
          showError = TRUE;
      }
    }
    
    public Attachment attach = new Attachment();
    public Blob bl {get; set;}
    public String contentType {get; set;}
    public String fileName {get; set;}
    public String VFPageURL {get; set;}
    public String errorMessage {get; set;}    
    public boolean showError {get; set;}
    public String showErrorString {get; set;}
        
    public PageReference save(){
        
        VFPageURL = '/apex/Attachments_Contacts?id=' + webContact.Id;
        if (bl != NULL) {
          attach.OwnerId = UserInfo.getUserId();
          attach.ParentId = webContact.Id;
          attach.Name = fileName;
          attach.Body = bl;
          attach.ContentType = contentType;
          showErrorString = 'FALSE';
          showError = FALSE;
          
          try {
            insert attach;
          } catch (DMLException e) {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));
          return null;
          } finally {
            attach = new Attachment();
          }
        } else {
          VFPageURL += '&showError=TRUE';
        }
                 
        PageReference p= new PageReference(VFPageURL);
        p.setRedirect(true);
        return p;
    }
}

 

 

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Very nice work mate.