Hello folks, today we will discuss how to upload Attachments via remote action (Jquery) in Visualforce page. First of all, we need a record id to upload the attachment so we will get recordId from the apex controller and then we create a Visualforce page to upload the attachments.
Apex Class: uploadattachCtrl
In the Apex class, we create a method for retrieving attachments for querying all related attachments from related parent records Also we create a remote action method for uploading the attachments
public class uploadattachCtrl {
public List<ContentVersion> lstContentVersionWrappers{get;set;}
public string objAttParentId{get;set;}
public uploadattachCtrl(){
for(Account acc : [select id from Account LIMIT 1]){
objAttParentId = acc.id;
}
this.retriveAttachments();
}
public void dummyrefresh(){
this.retriveAttachments();
}
public void retriveAttachments(){
try{
lstContentVersionWrappers = new list<ContentVersion>();
String strThreadId = '';
//string objAttParentId = '';
if(objAttParentId != null && string.isNotBlank(objAttParentId)){
set<String> ConDocIds = new set<String>();
for(ContentDocumentLink cdl : [select LinkedEntityId,ContentDocumentId from ContentDocumentLink where LinkedEntityId = : objAttParentId]){
ConDocIds.add(cdl.ContentDocumentId) ;
}
for(ContentVersion CV:[select id,title,description,createdbyid,ContentSize,lastmodifieddate,contentdocumentid from contentVersion where ContentDocumentId In :ConDocIds]){
lstContentVersionWrappers.add(CV);
}
}
}catch(Exception ex){
//handle catch
}
}
@RemoteAction
public static String uploadAttachments(String filename, String fileData, String record,String description) {
if(fileData==null)
return String.valueOf('Invalid file data.');
String base64 = fileData.substring(fileData.indexOf(',')+1);
Blob actualdata = EncodingUtil.base64Decode(base64);
try{
List<ContentVersion> FileListToInsert = new list<ContentVersion>();
ContentVersion cVersion = new ContentVersion();
cVersion.PathOnClient = filename;//File name with extention
cVersion.Title = filename;//Name of the file
cVersion.VersionData = actualdata;//File content
cVersion.Description = Description;
FileListToInsert.add(cVersion);
if(FileListToInsert.size()>0){
insert FileListToInsert;
Set<String> Condoc = new Set<String>();
set<id> ContentVersionID = new set<id>();
for(ContentVersion CV: FileListToInsert){
ContentVersionID.add(CV.Id);
}
for(ContentVersion cv: [select contentDocumentid from ContentVersion where id in : ContentVersionID]){
Condoc.add(cv.ContentDocumentId);
}
list<ContentDocumentLink> cldlist = new list<ContentDocumentLink>();
for(String s : Condoc){
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId =s;
cdl.LinkedEntityId = record;
cdl.sharetype = 'I';
cldlist.add(cdl);
}
if(cldlist.size()>0)
insert cldlist;
return String.valueOf('Upload Successful!');
}
/******* Insert Attachments ******/
Attachment attch = new Attachment();
attch.name = filename;
attch.parentId = record;
attch.body = actualdata;
insert attch;
/**********************************/
}catch(Exception ex){
System.debug(ex);
return String.valueOf('Error');
}
return String.valueOf('');
}
}
Visualforce Page: uploadattach
In the Visualforce page, we will set recordId variable in input hidden. Create a table to show the attachments list. For uploading the attachments we create a Modal Popup and create two fields. We will upload the attachment via the Jquery method without reloading the Page.
<apex:page controller="uploadattachCtrl">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<apex:slds />
<apex:form >
<apex:actionStatus id="mystatus" >
<apex:facet name="start">
<div style="position: fixed; left: 0; top: 0; bottom: 0; right: 0; z-index: 9999; margin: 30% 50%">
<!-- SPINNER -->
<div style=" position:fixed;left: 50%; top: 50%;height:32px; width:32px; margin-left: -32px; margin-top:-32px;z-index: 9999;" id="spinner" class="slds-spinner_container slds-is-relative" >
<div role="status" class="slds-spinner slds-spinner--large slds-spinner--brand">
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
<!-- / SPINNER -->
</div>
<div class="slds-backdrop slds-backdrop_open" style="opacity: 0;"></div>
</apex:facet>
</apex:actionStatus>
<!-- SPINNER -->
<div id="spinnerRemote" class="slds-hide" style="z-index:2000000">
<div class="demo-only">
<div class="slds-spinner_container">
<div role="status" class="slds-spinner slds-spinner_medium slds-spinner_brand" style="z-index: 2000000;position: fixed;">
<div class="slds-spinner__dot-a"></div>
<div class="slds-spinner__dot-b"></div>
</div>
</div>
<div class="slds-backdrop slds-backdrop_open" style="opacity: 0;"></div>
</div>
</div>
<!-- / SPINNER -->
<!-- Page Header Start -->
<div class="slds-tabs_card">
<div class="slds-page-header">
<div class="slds-page-header__row">
<div class="slds-page-header__col-title">
<div class="slds-media">
<div class="slds-media__figure">
<span class="slds-icon_container slds-icon-doctype-xml" title="Description of icon when needed">
<svg class="slds-icon slds-page-header__icon" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS, 'assets/icons/doctype-sprite/svg/symbols.svg#attachment')}" />
</svg>
<span class="slds-assistive-text">Description of icon when needed</span>
</span>
</div>
<div class="slds-media__body">
<div class="slds-page-header__name">
<div class="slds-page-header__name-title">
<h1>
<span class="slds-page-header__title slds-truncate" title="Rohde Corp - 80,000 Widgets">Attachments</span>
</h1>
</div>
</div>
<p class="slds-page-header__name-meta"></p>
</div>
</div>
</div>
<div class="slds-page-header__col-actions">
<div class="slds-page-header__controls">
<div class="slds-page-header__control">
<ul class="slds-button-group-list">
<li>
<button class="slds-button slds-button_neutral" onclick="ShowHideAtachmentPopup();return false">Add Attachment </button>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Page Header End -->
<!-- start attachment table -->
<apex:actionRegion >
<apex:actionFunction name="dummyrefresh" action="{!dummyrefresh}" reRender="AttachmentTablePanel,HandleAttachmentsPopUp,attachment_Popup_Content,AttachmentPopupFooter" status="mystatus"/>
</apex:actionRegion>
<apex:outputPanel id="AttachmentTablePanel">
<apex:outputPanel layout="block" id="WitnessTableId" styleClass="slds-m-top_small" >
<div style="min-width:10rem" class="slds-scrollable_x" >
<table id="WitnessTable" class="slds-table slds-table_bordered slds-table_fixed-layout slds-max-medium-table_stacked-horizontal">
<thead>
<tr class="slds-line-height_reset">
<th class="slds-text-title_caps">
<div class="slds-truncate"> Title </div>
</th>
<th class="slds-text-title_caps">
<div class="slds-truncate"> File Size </div>
</th>
<th class="slds-text-title_caps">
<div class="slds-truncate"> Description </div>
</th>
<th class="slds-text-title_caps">
<div class="slds-truncate"> Last Modified Date </div>
</th>
</tr>
</thead>
<tbody>
<apex:repeat value="{!lstContentVersionWrappers}" var="attachment">
<tr aria-selected="false" class="slds-hint-parent">
<td data-label="title" role="gridcell">
<apex:outputPanel >
{!attachment.Title}
</apex:outputPanel>
</td>
<td data-label="Size" role="gridcell">
<apex:outputText value="{!ROUND(attachment.ContentSize / 1000, 0)} KB" />
</td>
<td data-label="Description" role="gridcell">
<apex:outputText value="{!attachment.Description}" />
</td>
<td data-label="Date" role="gridcell">
<apex:outputText value="{0, date, MMMM d',' yyyy}">
<apex:param value="{!attachment.LastModifiedDate}" />
</apex:outputText>
</td>
</tr>
</apex:repeat>
</tbody>
</table>
</div>
</apex:outputPanel>
</apex:outputPanel>
</div>
<!-- ---->
<!---------------------------------------------------- Attachment Popup Starts ------------------------------------------------->
<div id="HandleAttachmentsPopUp" style="height: 640px;position: absolute;" class="slds-hide">
<section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<header class="slds-modal__header">
<button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" onclick="af_ResetAtt();return false;" title="Close">
<svg class="slds-button__icon slds-button__icon_large" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS, 'assets/icons/utility-sprite/svg/symbols.svg#close')}" />
</svg>
<span class="slds-assistive-text">Close</span>
</button>
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Add Attachment</h2>
</header>
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
<apex:outputPanel id="attachment_Popup_Content">
<input type="hidden" value="{!objAttParentId}" id="WitnessIDRemotee"/>
<apex:actionRegion >
<!---------------------- Attachment related action Functions -------------------------------------------->
<apex:actionFunction name="af_ResetAtt" rerender="HandleAttachmentsPopUp,attachment_Popup_Content,AttachmentPopupFooter" oncomplete="ShowHideAtachmentPopup();" status="mystatus"/>
<!------------------------------------------------------------------------------------------------------->
</apex:actionRegion>
<apex:outputPanel >
<div class="slds-text-body_regular"></div>
<div class="slds-text-body_regular slds-m-top_medium" style="font-style:italic;margin-left:10px;margin-bottom:15px;color:#d21e00;"></div>
<apex:actionRegion >
<div class="slds-form-element">
<label class="slds-form-element__label" for="form-element-01">File</label>
<div class="slds-form-element__control ">
<input type="file" id="fileInput" value="" fileName=""/>
</div>
<div style="height:0.7rem;"></div>
<label class="slds-form-element__label" for="form-element-01">Description</label>
<div class="slds-form-element__control ">
<textarea id="description_input" placeholder="" class="slds-textarea" autocomplete="none"></textarea>
</div>
</div>
</apex:actionRegion>
</apex:outputPanel>
</apex:outputPanel>
</div>
<apex:outputPanel id="AttachmentPopupFooter" layout="block" styleclass="slds-modal__footer">
<apex:outputPanel >
<button class="slds-button slds-button_neutral" onclick="af_ResetAtt();return false;">Cancel</button>
<button class="slds-button slds-button_brand" onclick="af_AttachmentSaveJquery();return false;" >Save</button>
</apex:outputPanel>
</apex:outputPanel>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</div>
<script>
function ShowHideAtachmentPopup(){
var popUp=$('div[id$=HandleAttachmentsPopUp]');
if($(popUp).hasClass('slds-hide')){
$(popUp).removeClass('slds-hide').addClass('slds-show');
}else if($(popUp).hasClass('slds-show')){
$(popUp).removeClass('slds-show').addClass('slds-hide');
}
}
/*************************** Upload files via jquery **************************************************/
function af_AttachmentSaveJquery() {
var popUp=$('div[id$=HandleAttachmentsPopUp]');
$('#spinnerRemote').addClass('slds-show').removeClass('slds-hide');
var recordId = $('#WitnessIDRemotee').val();
var jsonObj = [];
let spinneroff = true;
for(var i=1;i<=1;i++){
let fileInput = $('#fileInput');
let fileDescription = $('#description_input').val();
if (!$.trim( fileInput.val() ).length == 0) {
spinneroff = false;
let file = fileInput[0].files[0];
let fileName = getFileNameWithExtension(file);
let reader = new FileReader();
let item = {}
item["filename"] = fileName;
item["description"] = fileDescription;
reader.onloadend = function(){
item["filedata"] = reader.result;
uploadToSalesforce(fileName,reader.result,recordId,fileDescription);
}
reader.readAsDataURL(file);
}
}
console.log(spinneroff);
if(spinneroff){
$('#spinnerRemote').addClass('slds-hide').removeClass('slds-show');
$(popUp).removeClass('slds-show').addClass('slds-hide');
}
}
function uploadToSalesforce(fileName,contentOfFile,recordForWhichUploading,description) {
var popUp=$('div[id$=HandleAttachmentsPopUp]');
$('#spinnerRemote').addClass('slds-show').removeClass('slds-hide');
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.uploadattachCtrl.uploadAttachments}',
fileName, contentOfFile, recordForWhichUploading,description,
function(result, event){
console.log(result);
$('#spinnerRemote').addClass('slds-hide').removeClass('slds-show');
$(popUp).removeClass('slds-show').addClass('slds-hide');
dummyrefresh();
if (event.status) {
status = 'Upload Successful' + result;
} else if (event.type === 'exception') {
status = 'Upload Error';
} else {
status = 'Upload Error';
}
},
{escape: true}
);
}
function getFileNameWithExtension(file) {
var extIndex = file.name.lastIndexOf('.');
var extension = file.name.substring(extIndex);
var fileName = file.name.substring( 0, extIndex );
fileName = fileName.replace(/\./g, '_');
fileName += extension;
return fileName;
}
/*******************************************************************************************************/
</script>
</apex:form>
</apex:page>
2 comments
No remote action found error
Check apex class and method annotation should be @remoteAction