Issue with assigning file to attachment field on new record
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-19-2023 10:47 AM
I have a UI macro that calls a UI page popup that presents a basic form. The idea is user fills out form and a new record will be generated in a table I have called attachment. Almost everything works except the actual file selected for the attachment does not get added to the new record.
UI Page:
HTML:
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<style>
/* Add custom styles for the table */
table {
border-collapse: separate;
border-spacing: 0 10px; /* Adjust the vertical spacing between rows */
width: 100%;
}
/* Add padding to the table cells */
td {
padding: 5px;
}
/* Add rounded corners to the input boxes */
input[type="text"],
input[type="file"],
textarea {
border-radius: 5px;
}
/* Add spacing between labels and input fields */
td > label {
margin-bottom: 5px; /* Adjust the spacing as needed */
text-align: left; /* Align labels to the left */
display: block; /* Place each label on a new line */
width: 100%; /* Adjust the width of labels as needed */
}
/* Add styles for the subtext */
.subtext {
font-size: 12px;
color: #888;
margin-top: 5px; /* Adjust the spacing between labels and input fields */
text-align: left; /* Align the subtext to the left */
}
/* Add class for table rows */
.input-row {
display: block; /* Place each input section in a new line */
}
</style>
<g:ui_form>
<table>
<tr>
<td>
<label>Title:</label>
<div class="subtext">(Please enter short description or name of attachment)</div>
<input type="text" name="title" id="title" required="true" />
</td>
</tr>
<tr>
<td>
<label>Alternate Location of saved file:</label>
<input type="text" name="location" id="location" class="input-row" />
</td>
</tr>
<tr class="input-row">
<td>
<label>Attachment:</label>
<input type="file" name="attachment" id="attachment" />
</td>
</tr>
<tr>
<td>
<label>Notes:</label>
<textarea name="notes" id="notes" class="input-row"></textarea>
</td>
</tr>
</table>
<div>
<g:dialog_buttons_ok_cancel
ok_id="submitData"
ok="return continueOK()"
ok_type="button"
ok_text="${gs.getMessage('Okay')}"
ok_style_class="btn btn-primary"
cancel_type="button"
cancel_id="cancelData"
cancel_style_class="btn btn-default"
cancel="return continueCancel()" />
</div>
</g:ui_form>
</j:jelly>
Client Script:
function continueOK() {
//lets pull in the form input to be used to create an attachment record
var title = gel('title').value;
var location = gel('location').value;
var attachment = gel('attachment').value;
var notes = gel('notes').value;
var sysID = g_form.getUniqueValue();
//alert("OK clicked - " + title + ", " + location + ", " + attachment + ", " + notes + ", " + sysID) ;
// Create a new instance of GlideAjax
var ga = new GlideAjax('x_cinep_incident_0.iltAjaxUtil');
ga.addParam('sysparm_name', 'addAttachment');
ga.addParam('sysparm_sysId', sysID);
ga.addParam('sysparm_title', title);
ga.addParam('sysparm_location', location);
ga.addParam('sysparm_attachment', attachment);
ga.addParam('sysparm_notes', notes);
ga.getXML(addAttachmentCallback);
GlideDialogWindow.get().destroy();
}
function continueCancel() {
//alert("Cancel clicked");
GlideDialogWindow.get().destroy();
}
function addAttachmentCallback(response) {
var message = response.responseXML.documentElement.getAttribute('answer');
alert(message);
}
Script include(GlideAjax):
var iltAjaxUtil = Class.create();
iltAjaxUtil.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
addAttachment: function() {
try {
var iltSysID = this.getParameter('sysparm_sysId');
var title = this.getParameter('sysparm_title');
var location = this.getParameter('sysparm_location');
var attachment = this.getParameter('sysparm_attachment');
var notes = this.getParameter('sysparm_notes');
//lets create a new Attachment record and populate it with the provided information.
var grAttach = new GlideRecordSecure('x_cinep_incident_0_attachments');
grAttach.initialize();
grAttach.setValue("title", title);
grAttach.setValue("ilt", iltSysID);
grAttach.setValue("attachment", attachment);
grAttach.setValue("alternate_location_of_saved_file", location);
grAttach.setValue("notes", notes);
grAttach.insert();
return 'Attachment added successfully';
} catch (ex) {
return ex;
}
},
Here are some screen grabs of what is happening
POPUP:
List showing no file attached:
Record with no file attached
Any assistance would be appreciated.
Thanks,
Brandon
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-20-2023 03:56 AM
Hi @Brandon P1 ,
It seems that the issue lies in how you handle the file attachment in your UI macro and script. In JavaScript, you cannot directly access the file path or content of a file input field due to security restrictions. Instead, you need to use the FormData object to handle file uploads
UI Page:
Add an onsubmit attribute to your form tag to call the 'continueOK' function:
<g:ui_form onsubmit="return continueOK()">
Client Script:
Replace the continueOK function with the updated version below:
function continueOK() {
// Create a new instance of FormData
var formData = new FormData();
// Append the form data to the FormData object
formData.append('title', gel('title').value);
formData.append('location', gel('location').value);
formData.append('attachment', gel('attachment').files[0]);
formData.append('notes', gel('notes').value);
formData.append('sysID', g_form.getUniqueValue());
// Create a new XMLHttpRequest object
var xhr = new XMLHttpRequest();
xhr.open('POST', 'x_cinep_incident_0.iltAjaxUtil.addAttachment', true);
// Set the onload callback function
xhr.onload = function () {
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
addAttachmentCallback(response);
} else {
// Handle the error case
addAttachmentCallback({ answer: 'Error: ' + xhr.status });
}
};
// Send the FormData object with the XMLHttpRequest
xhr.send(formData);
// Prevent the default form submission
return false;
}
Script Include (GlideAjax):
Modify the addAttachment function to handle file attachments properly and return the response as JSON:
addAttachment: function() {
try {
var iltSysID = this.getParameter('sysparm_sysId');
var title = this.getParameter('sysparm_title');
var location = this.getParameter('sysparm_location');
var attachment = this.getParameter('sysparm_attachment');
var notes = this.getParameter('sysparm_notes');
// Handle file attachment
var attachmentSysID = '';
if (attachment) {
var grAttachment = new GlideSysAttachment();
attachmentSysID = grAttachment.write('x_cinep_incident_0_attachments', iltSysID, attachment);
}
// Create a new Attachment record and populate it with the provided information
var grAttach = new GlideRecordSecure('x_cinep_incident_0_attachments');
grAttach.initialize();
grAttach.setValue('title', title);
grAttach.setValue('ilt', iltSysID);
grAttach.setValue('attachment', attachmentSysID);
grAttach.setValue('alternate_location_of_saved_file', location);
grAttach.setValue('notes', notes);
grAttach.insert();
return { answer: 'Attachment added successfully' };
} catch (ex) {
return { answer: 'Error: ' + ex };
}
},
With these modifications, the file attachment will be properly handled using FormData in the client script, and the attachment will be written to the record in the script include. The response from the server will be returned as JSON and passed to the "addAttachmentCallback" function for further processing.
Regards,
Shravan
Please mark this as helpful and correct answer, if this helps you
Shravan
Please mark this as helpful and correct answer, if this helps you
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-21-2023 07:24 AM
I had posted a response to this yesterday but seems to have been removed.
First, thanks for the response!
So I have implemented the changes suggested, however I am now running into a client side error. The
var response = JSON.parse(xhr.responseText);
line is not receiving a JSON as expected, instead is receiving a large HTML doc. the error that the browser is throwing is as follows:
3545:1 Uncaught SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
at JSON.parse (<anonymous>)
at xhr.onload (eval at evalScript (VM2826 js_includes_doctype.jsx:76:29), <anonymous>:16:33)
xhr.onload @ VM3541:16
load (async)
continueOK @ VM3541:13
onclick @ VM3544 x_cinep_incident_0_incident_loss_tracker.do:1
I am including the updated code for reference
UI page: HTML
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<style>
/* Add custom styles for the table */
table {
border-collapse: separate;
border-spacing: 0 10px; /* Adjust the vertical spacing between rows */
width: 100%;
}
/* Add padding to the table cells */
td {
padding: 5px;
}
/* Add rounded corners to the input boxes */
input[type="text"],
input[type="file"],
textarea {
border-radius: 5px;
}
/* Add spacing between labels and input fields */
td > label {
margin-bottom: 5px; /* Adjust the spacing as needed */
text-align: left; /* Align labels to the left */
display: block; /* Place each label on a new line */
width: 100%; /* Adjust the width of labels as needed */
}
/* Add styles for the subtext */
.subtext {
font-size: 12px;
color: #888;
margin-top: 5px; /* Adjust the spacing between labels and input fields */
text-align: left; /* Align the subtext to the left */
}
/* Add class for table rows */
.input-row {
display: block; /* Place each input section in a new line */
}
</style>
<g:ui_form onsubmit="return continueOK()">
<table>
<tr>
<td>
<label>Title:</label>
<div class="subtext">(Please enter short description or name of attachment)</div>
<input type="text" name="title" id="title" required="true" />
</td>
</tr>
<tr>
<td>
<label>Alternate Location of saved file:</label>
<input type="text" name="location" id="location" class="input-row" />
</td>
</tr>
<tr class="input-row">
<td>
<label>Attachment:</label>
<input type="file" name="attachment" id="attachment" />
</td>
</tr>
<tr>
<td>
<label>Notes:</label>
<textarea name="notes" id="notes" class="input-row"></textarea>
</td>
</tr>
</table>
<div>
<g:dialog_buttons_ok_cancel
ok_id="submitData"
ok="return continueOK()"
ok_type="button"
ok_text="${gs.getMessage('Okay')}"
ok_style_class="btn btn-primary"
cancel_type="button"
cancel_id="cancelData"
cancel_style_class="btn btn-default"
cancel="return continueCancel()" />
</div>
</g:ui_form>
</j:jelly>
UI Page: Client Script
function continueOK() {
var formData = new FormData();
formData.append('title', gel('title').value);
formData.append('location', gel('location').value);
formData.append('attachment', gel('attachment').files[0]);
formData.append('notes', gel('notes').value);
formData.append('sysID', g_form.getUniqueValue());
var xhr = new XMLHttpRequest();
xhr.open('POST', 'x_cinep_incident_0.iltAjaxUtil.addAttachment', true);
xhr.onload = function() {
if (xhr.status === 200) {
console.log('<BP>continueOK: Response - ' + xhr.responseText);
var response = JSON.parse(xhr.responseText);
addAttachmentCallback(response);
} else {
console.log('<BP>continueOK: Error - ' + xhr.status);
addAttachmentCallback({
answer: 'Error: ' + xhr.status
});
}
};
xhr.send(formData);
return false;
}
function continueCancel() {
GlideDialogWindow.get().destroy();
}
function addAttachmentCallback(response) {
var message = response.answer; // Access the 'answer' property directly
alert(message);
}
Script Include
var iltAjaxUtil = Class.create();
iltAjaxUtil.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
addAttachment: function() {
try {
gs.info('<BP> iltAjaxUtil:addAttachment: start ');
var iltSysID = this.getParameter('sysparm_sysId');
var title = this.getParameter('sysparm_title');
var location = this.getParameter('sysparm_location');
var attachment = this.getParameter('sysparm_attachment');
var notes = this.getParameter('sysparm_notes');
var attachmentSysID = '';
if (attachment) {
var grAttachment = new GlideSysAttachment();
attachmentSysID = grAttachment.write('x_cinep_incident_0_attachments', iltSysID, attachment);
}
var grAttach = new GlideRecordSecure('x_cinep_incident_0_attachments');
grAttach.initialize();
grAttach.setValue('title', title);
grAttach.setValue('ilt', iltSysID);
grAttach.setValue('attachment', attachmentSysID);
grAttach.setValue('alternate_location_of_saved_file', location);
grAttach.setValue('notes', notes);
grAttach.insert();
return this.newItem('answer', 'Attachment added successfully');
} catch (ex) {
gs.info('<BP> iltAjaxUtil:addAttachment: Error - ' + ex);
return {
answer: 'Error: ' + ex
};
}
},
type: 'iltAjaxUtil'
});
and here is a picture of the document being logged
Any suggestions or help would be very much appreciated, and thank you so much.
Brandon