- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 07-10-2018 07:21 PM
This is a very tricky thing in ServiceNow and usually any work related to sys_attachment table is always a bit of a hack. So ServiceNow handles the attachments through two tables – sys_attachment and sys_attachment_docs. For a better understanding refer to this article https://community.servicenow.com/community?id=community_article&sys_id=870d2ea5dbd0dbc01dcaf3231f961...
In gist, sys_attachment table is just a reference, pointing to a record against which attachments are attached, whereas the sys_attachment_docs table actually holds the data of the actual attachment divided into chunks of 4K.
Issue with categorisation of attachment is due to the fact that any attachment is refereed against a record and there is no out of the box mechanism to segregate attachments within a record. The best possible or only solution is to add a suffix or prefix to the attachment name to categorise it accordingly.
I am going to discuss the approach that I implemented for a client very recently -
I placed a widget in the page and called it two with two different Macro variables.
Basic HTML Code:
<div class="m-t-n">
<span class="file-upload-input clearfix">
<input type="file" style="display: none" multiple="true" ng-file-select="parent.attachmentHandler.onFileSelect($files)" class="sp-attachments-input">
<a href="javascript:void(0)" id="attachment_add" ng-click="parent.attachmentHandler.openSelector($event);" class="btn btn-primary sp-attachment-add">
<span class="glyphicon glyphicon-paperclip"></span>
<span ng-if="field=='u_attachment_internal'" ng-click="c.saveAttach('internal')">${Add Attachments for internal use only (IUO)}</span>
<span ng-if="field=='u_attachment_external'" ng-click="c.saveAttach('external')">${Add Attachments to be sent to customer (STC)}</span>
</a>
</span>
</div>
<style>
[id="sp_formfield_IO:{{attachment_field}}"]{
display: none;
}
[id="{{attachment_field}}"] fieldset,
[id="{{attachment_field}}"] > .form-group {
margin: 0;
}
</style>]]
This part is doing three things:
- It’s a widget which is embedded in a parent widget, hence attachmentHandler.onFileSelect($files). So it’s basically connecting the selected files to the attachment handler defined in the parent widget.
- It has two spans, and it shows each based on which variable is calling the widget at that instance.
- On clicking the respective visible span, it triggers the c.saveAttach function and depending on which one you clicked it sends a string as a parameter.
Client Script part
function getParent(parent) {
if (parent.item) {
return parent;
} else {
if (parent.$parent){
return getParent(parent.$parent);
} else {
}
}
}
c.saveAttach = function (str){
$scope.external= g_form.getValue('u_attachment_external')||"";
$scope.internal= g_form.getValue('u_attachment_internal')||"";
var oldVLength;
var newVLength;
var diff;
var unbindFn = $scope.$watch('parent.attachments', function(newValue, oldValue) {
oldVLength = oldValue.length;
newVLength = newValue.length;
diff=parseInt(newValue.length-oldValue.length);
if(newValue.length>0 && oldValue.length==0){
for(i=0;i<newValue.length;i++){
if(str=='internal'){
$scope.internal+=(JSON.stringify($scope.parent.attachments[i].sys_id))+',';
}
else if(str=='external'){
$scope.external+=(JSON.stringify($scope.parent.attachments[i].sys_id))+',';
}
}
g_form.setValue('u_attachment_internal',$scope.internal);
g_form.setValue('u_attachment_external',$scope.external);
unbindFn();
}
if(newValue.length>oldValue.length && oldValue.length>0){
for(j=0;j<diff;j++){
if(str=='internal'){
$scope.internal+=(JSON.stringify($scope.parent.attachments[j].sys_id))+',';
g_form.setValue('u_attachment_external',$scope.external);
}
else if(str=='external'){
$scope.external+=(JSON.stringify($scope.parent.attachments[j].sys_id))+',';
g_form.setValue('u_attachment_internal',$scope.internal);
}
}
g_form.setValue('u_attachment_internal',$scope.internal);
g_form.setValue('u_attachment_external',$scope.external);
unbindFn();
}
});
}
This is the client script part which does all the trick –
So the getParent() function is used to link with the parent widget here.
The c.saveAttach() function starts a watch function to watch the parent.attachments.
If there is a newValue which means that there is an attachment attached, so it checks the string parameter passed when the function was called. If the string is internal, then it stores the sys_id of the attachment in a scope variable called internal and the other way round for external. At the end of the watch, since this is will refresh the scope so we need to store the content of the $scope.internal or $scope.external to the fields which are using the widget respectively. Also note, we declare the watch as a function called unbindFn() this is to end the watch function, which is achieved by calling the function after the internal or external sys_ids are stored in the respective field variables.
Next after the form is submitted, we ran a business rule (after insert or async insert) to grab the sys_id of the internal attachment stored in the variable 'u_attachment_internal' and rename the files of those sys_id with a prefix “INT” - and the same for external attachment stored in 'u_attachment_external' with prefix “EXT”.
We can also use a macro to show the filenames in two table called External Attachment and Internal Attachment, without even renaming simply by grabbing the sys_id from the variables 'u_attachment_internal' and 'u_attachment_external'
Hopefully it will help some of you to tackle issues related to the Attachment Categorisation.
- 1,882 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Sam Dey1 awesome solution!!!
Can you please show the widget and page setup and macro field configuration as well? Thanks