Skip to main content

There are many requirements where Approvers need to upload attachments on task form, which need to be uploaded on main item instead of task form.

I have achieved it using REST and JS.

 

Major Steps :

1. Create RichText Control on Text Form to show attachment and add attachment button.

2. Add JS which use REST API to add attachments

 

Requirement Result Screen :

 

On click of Show Attachment button, it loads attachments of Related item with add attachment link as shown below

 

on Add attachment it opens below screen and we can upload attachment by selecting file.

 

 

Solution

1. Drag a Task on workflow. Click on Edit Task form.

2. Add a Rich Text Control on form as shown in below screen

3. Edit Properties of Rich Text add below HTML in Rich text as shown below 

<input id="btnAttach" ="return checkSPLoad('');" style="width:180px;" type="button" value="Show Attachments" />

<div id="divAttachs"></div>

<div id="addAttachmentDiv" style="display:none;">Select a file<br />
      <strong>Name </strong>

      <input class="attachmentButton" id="attachmentButton" multiple="multiple" name="attachmentButton" ="attachFile(this);" type="file" />

</div>

<div class="nf-attachmentsLink" id="idAttachmentsLink" ="showAttch();" style="height:17px;display:none;">

      <img  />

        <a class="ms-addnew" href="#">Add Attachment</a>

</div>

 

4. Click On Save.

5. Select Form Setting in ribbon and add javascript.

6. Paste below script in custom javascript section.

var pollSP;  var hostweburl='';
var appweburl='';
var listname='ListName';//Include list name 
var itemid=ID;  //Include reference of ID of item.

var file;
var contents;
var itmUrl='';  
function checkSPLoad(callType){
 NWF$('#btnAttach').hide();
    if (clientContext){ 
        window.clearInterval(pollSP); 
        hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
        appweburl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl")); 
        var layoutsPath = "/_layouts/15/"; 
        var scriptbase = appweburl + layoutsPath; 
        itmUrl=hostweburl+"/Lists/"+listname+"/Attachments/"+itemid;
        if(callType=='Post')
        {
               NWF$.getScript(scriptbase + "SP.js", function () {
                            NWF$.getScript(scriptbase+ "SP.RequestExecutor.js", execCrossDomainRequest);
               });
        }   
      else
        {
                  NWF$.getScript(scriptbase + "SP.js",   function () {
                            NWF$.getScript(scriptbase+ "SP.RequestExecutor.js", execCrossDomainGetRequest);
               });
        }
    } 
 
    function execCrossDomainRequest() {  
        var contents2 = _arrayBufferToBase64(contents);
        var executor = new SP.RequestExecutor(appweburl);             
        var digest =     NWF$("#__REQUESTDIGEST").val();  
        executor.executeAsync(  
          {         
            url:appweburl +   
            "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('"+listname+"')/items("+itemid+")/AttachmentFiles/add(FileName='"+file.name                   +"')?               @target='" +      hostweburl + "'",   
            method: "POST",   
            body: contents2 ,  
            binaryStringRequestBody: true,
            contentType: "application/json;odata=verbose",         
            headers: {            "X-RequestDigest": digest, "Accept": "application/json; odata=verbose"},                      
            success: function (data) {  
                   NWF$('#addAttachmentDiv').hide();
                   NWF$('#attachmentButton').val('');
                   execCrossDomainGetRequest();    NWF$('#idAttachmentsLink').show();
            },  
            error: function (err) {  
                var data=JSON.parse(err.body);
                ;
                   NWF$('#idAttachmentsLink').show(); 
                         NWF$('#addAttachmentDiv').hide();
                            NWF$('#attachmentButton').val('');    
            }   
        });                             
    }
   
 function execCrossDomainGetRequest() {  
       var executor = new SP.RequestExecutor(appweburl);             
        NWF$('#divAttachs').html("Loading...");
        executor.executeAsync(  
            {         
             url:     appweburl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('"+listname+"')/items("+itemid+")/AttachmentFiles?@target='" +   
                         hostweburl + "'",   
             method: "GET",   
             headers: { "Accept": "application/json; odata=verbose" },                   
                success: function (data) { 
                    parseAttachment(data);
                             NWF$('#idAttachmentsLink').show();
                },  
   error: function (err) {  
    var data=JSON.parse(err.body);
     ; NWF$('#btnAttach').show(); 
    }   
   });                             
 }
}
function getQueryStringParameter(paramToRetrieve) {   
    var params =   
        document.URL.split("?")_1].split("&");     
    for (var i = 0; i < params.length; i = i + 1) {   
        var singleParam = params.split("=");   
        if (singleParamb0] == paramToRetrieve)   
            return singleParamÂ1];   
    }   
}
function showAttch()
{
 NWF$('#addAttachmentDiv').show();
 NWF$('#idAttachmentsLink').hide();
} 
function parseAttachment(vdata)
{
 var html='';
 var data=JSON.parse(vdata.body);
 var items=data.d.results;
 for(i=0;i<items.length;i++)
 {
  html+='<a href="'+itmUrl+'//'+items.FileName+'" target="_blank">'+items.FileName+'</a><br>';
 }
 NWF$('#divAttachs').html(html);
}
function f"font-size: 12px;">    contents = event.target.result;
    checkSPLoad('Post');;
}
function attachFile(event) {
    var i = 0,
    files = event.files,
    len = files.length;
 if (files.length > 0) {
        file = files<0];
        fileName = file.name;
        var reader = new window.FileReader();
        reader. f"font-size: 12px;">        reader. = function(event) {
            console.error("File reading error " + event.target.error.code);
        };
        reader.readAsArrayBuffer(file);
    }      
    return false;
}
function _arrayBufferToBase64(buffer) {
    var binary = '';
    var bytes = new window.Uint8Array(buffer);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes);
    }
    return binary;
}


 Note : Update list name and id(Add reference from Item section) in top of script.

7. Save and close form.

 

Publish workflow and test.

 

Happy Nintexing.

This looks promising but you've got some typos in there. Can you correct those?

 

function f"font-size: 12px;">    contents = event.target.result;
    checkSPLoad('Post');;
}

function attachFile(event) {
    var i = 0,
    files = event.files,
    len = files.length;
 if (files.length > 0) {
        file = files[0];
        fileName = file.name;
        var reader = new window.FileReader();
        reader. f"font-size: 12px;">        reader. = function(event) {
            console.error("File reading error " + event.target.error.code);
        };
        reader.readAsArrayBuffer(file);
    }       
    return false;
}

 


Hi,

 

that is a great post, but i agree, can you just take a look at the typo issue.

Alternative solution (but I prefere yours) on this post


Hi,



 



The aim of this script is great, so I have corrected it and updated it. I have use it for SharePoint On-premise 2013. You will find the corrected code below :



 



The Html to put into the Rich text control :



<input id="btnAttach" onclick="return checkSPLoad('');" type="button" value="Show Attachments" style="width: 180px;" />



<div id="divAttachs">

</div>



<div id="addAttachmentDiv" style="display: none;">

Select a file<br />

<strong>Name </strong>

<input class="attachmentButton" id="attachmentButton" name="attachmentButton" type="file" />

</div>



<div class="nf-attachmentsLink" id="idAttachmentsLink" onclick="showAttch();" style="height: 17px; display: none;">

<br />

<img src="/_layouts/15/NintexForms/images/NF_16x16_RepeaterAddRow.png" alt="" />

<a class="ms-addnew" href="#" onclick="return false;">Add Attachment</a>

</div>





The JavaScript code to put into the form :



var pollSP;

var hostweburl = '';

var appweburl = '';

var listname = 'List Name'; //Include list name

var itemid = ID; //Include reference of ID of item.var file;

var contents;

var itmUrl = '';

var binaryContents;

var clientContext;


document.addEventListener("DOMContentLoaded", function () {

SP.SOD.executeFunc('sp.js', 'SP.ClientContext', exec);

});



function exec() {

clientContext = SP.ClientContext.get_current();

}



function checkSPLoad(callType) {

NWF$('#btnAttach').hide();

if (clientContext) {

window.clearInterval(pollSP);

hostweburl = _spPageContextInfo.siteAbsoluteUrl;

appweburl = _spPageContextInfo.webAbsoluteUrl;

var layoutsPath = "/_layouts/15/";

scriptbase = appweburl + layoutsPath;

itmUrl = hostweburl + "/Lists/" + listname + "/Attachments/" + itemid;

if (callType == 'Post') {

execPOSTRequest();

} else {

execGETRequest();

}

}

}



function onQueryFailed(sender, args) {

console.log('Request failed. ' + args.get_message() + '

' + args.get_stackTrace());

}



function execPOSTRequest() {

console.log("execPOSTRequest");

binaryContents = _arrayBufferToBase64(contents);

digest = NWF$("#__REQUESTDIGEST").val();



NWF$.getScript(scriptbase + "SP.RequestExecutor.js", function () {

var createitem = new SP.RequestExecutor(_spPageContextInfo.webServerRelativeUrl);

createitem.executeAsync({

url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/GetByTitle('" + listname + "')/items(" + itemid + ")/AttachmentFiles/add(FileName='" + file.name + "')",

method: "POST",

headers: {

"X-RequestDigest": digest,

"Accept": "application/json; odata=verbose",

"content-type": "application/json;odata=verbose",

},

binaryStringRequestBody: true,

body: binaryContents,

success: function (data) {

NWF$('#addAttachmentDiv').hide();

NWF$('#attachmentButton').val('');

execGETRequest();

NWF$('#idAttachmentsLink').show();

},

error: function (err) {

var data = err.body;

NWF$('#idAttachmentsLink').show();

NWF$('#addAttachmentDiv').hide();

NWF$('#attachmentButton').val('');

},

state: "Update"

});

});

}

var globdata;

function execGETRequest() {

console.log("execGETRequest");

NWF$('#divAttachs').html("Loading...");



NWF$.ajax({

url: appweburl + "/_api/web/lists/getbytitle('" + listname + "')/items(" + itemid + ")/AttachmentFiles",

method: "GET",

headers: {

"accept": "application/json;odata=verbose",

"content-type": "application/json;odata=verbose",

},

dataType: 'json',

async: false,

success: function (data) {



globdata = data;

parseAttachment(data);

NWF$('#idAttachmentsLink').show();

},

error: function (err) {

var data = err.body;

NWF$('#btnAttach').show();

}

});

}



function getQueryStringParameter(paramToRetrieve) {

GetUrlKeyValue(paramToRetrieve);

}



function showAttch() {

NWF$('#addAttachmentDiv').show();

NWF$('#idAttachmentsLink').hide();

}



function parseAttachment(vdata) {

var html = '';

var data = vdata;

var items = data.d.results;

var webappUrl = window.location.protocol + "//"+ window.location.host;



for (i = 0; i < items.length; i++) {

var v_curItem = items[i];

html += '<a href="' + webappUrl + v_curItem.ServerRelativeUrl + '" target="_blank">' + v_curItem.FileName + '</a><br />';

}

NWF$('#divAttachs').html(html);

}



NWF$('#attachmentButton').change(function(e){

fileName = e.target.files[0].name;

file = e.target.files[0];



var reader = new FileReader();

reader.onload = function(evt){

contents = evt.target.result;

checkSPLoad('Post')

};

reader.readAsArrayBuffer(e.target.files[0]);





});



function _arrayBufferToBase64(buffer) {

var binary = '';

var bytes = new window.Uint8Array(buffer);

var len = bytes.byteLength;

for (var i = 0; i < len; i++) {

binary += String.fromCharCode(bytes[i]);

}

return binary;

}


 






It's not perfect & some improvement could be done on this topic.


Reply