
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-03-2018 11:34 PM
Hi,
I am a newbie to Service Portal.
I have to create a page on which there are 2 dropdowns and 1 button.
In the first drop-down, there are tables which extend the Task table.
In the second drop-down, there are options(xls,docx) in which format user wants to download the file.
On click of a button, a user should get the file downloaded with the 'list of column labels and names of the table choose from first drop-down and add/insert the data into the (xls,docx) file'.
My questions are:
1. How to send the chosen table to server from client OR is there any other alternative to get all the columns of the table at client side?
2. How to download a (docs,xls) file on click of a button with the column labels and names in it?
Please find below what I have coded.
HTML Template:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Green Folder</title>
</head>
<body>
<div>
<div class="form-group" >
<select class="form-control" id="sel1" ng-model="optionText" ng-options="value for value in data.tables">
<option value="" disabled selected hidden>Select Table</option>
</select>
</div>
<div class="form-group" >
<select class="form-control" id="format">
<option value="" disabled selected hidden>Select Format</option>
<option value="xls">xls</option>
<option value="docx">docx</option>
</select>
</div>
<div class="container">
<button type="submit" class="btn btn-default" ng-click="c.getMergeFields();">Get Merge Fields</button>
</div>
</div>
</body>
</html>
Client Script:
function() {
/* widget controller */
var c = this;
var optionText = c.data.tables;
console.log("Option Text: " + optionText);
c.getMergeFields = function(){
var tableName= document.getElementById('sel1').value
console.log("Table name: " + tableName);
c.server.getmFields(tableName).then(function(resp){
var getfields = resp.data.mFields;
});
}
}
Server Script:
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
data.tables = getExtendTables();
function getExtendTables(){
//To fetch tables those extends Task table
gs.include('TableUtils');
var table = new global.TableUtils("task");
var tableList = table.getAllExtensions();
tableList = tableList.toString();
gs.info("tableList of type " + typeof tableList + " == " + tableList);
tableList = tableList.slice(1,-1);
gs.info("Slicing of tableList of type: " + typeof tableList + " here: " + tableList);
var arr = tableList.split(",");
gs.info("Arr: " + arr);
arr.sort();
return arr;
}
//To fetch column labels and name of table selected by user
if(input){
data.mFields = getmFields(input.tableName);
gs.info("mFields: " + mFields);
}
function getmFields(tableName){
gs.info("Input: " + tableName);
var gr = new GlideRecord(tableName);
gr.initialize();
gr.query();
gr.next();
var elements = gr.getElements();
var element;
var result = [];
for (var i=0; i<elements.length; i++) {
element = elements[i];
result[i]=element.getLabel();
}
result.sort();
gs.info("Result: " + result);
return result;
}
})();
Is there any better approach or best practice for this?
Any help would be appreciated.
Thanks in advance!
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-05-2018 03:48 AM
Hi Nikita,
The code I gave you exactly does the same thing. Please see below screenshot and updated code
if(input){
columnArray = [];
data.fields = $sp.getListColumns(input.table, 'default');
data.fields_array = data.fields.split(',');
var grForLabels = new GlideRecord(input.table);
for (var i in data.fields_array) {
console.log('going here');
var field = data.fields_array[i];
var ge = grForLabels.getElement(field);
if (ge == null)
continue;
var dataobj = {};
dataobj.value = field.toString();
dataobj.text = ge.getLabel().toString();
columnArray.push(dataobj);
}
data.columnDetails = columnArray;
}

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-05-2018 12:21 PM
Hi Nikita,
there seems to be an issue, whether input.tables are returning table or not.
instead of directly using input.tables, fir store into a variable like
var Inouttable = input,tables; and try the code.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-05-2018 08:18 PM
Hi Rahul,
input.tables is returning selected value as expected.
Yes, I did try this, but nothing worked out. I am getting the value printed correctly in logs.
I think methods are not able to understand the value from input.tables or something is missing in it.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-06-2018 12:32 AM
Hi Rahul,
Your code worked out.
There was a space in input.tables value like " incident" instead of "incident", due to which it was not processing.
Thank you so much for the help! 🙂
In future, if anyone comes up for the same issue below is updated code:
Server Script:
if(input){
columnArray = [];
data.fields = $sp.getListColumns(input.tables, 'default');
data.fields_array = data.fields.split(',');
var grForLabels = new GlideRecord(input.tables);
dataobj = function(){
this.value="";
this.text="";
this.toString = function(){
return "Data: " + this.value + ": " + this.text;
};
}
for (var i in data.fields_array) {
var field = data.fields_array[i];
var ge = grForLabels.getElement(field);
if (ge == null)
continue;
var col = new dataobj();
col.value = field.toString();
col.text = ge.getLabel().toString();
columnArray.push(col);
}
data.columnDetails = columnArray;
}
Client script:
$scope.getMergeFields = function(){
$scope.data.tables = $scope.options;
$scope.server.update().then(function(){
for(var f in $scope.data.columnDetails){
console.log("F: " + $scope.data.columnDetails[f].toString() + " : " + $scope.data.columnDetails[f].text + " : " + $scope.data.columnDetails[f].value);
}
})
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-05-2018 07:42 PM
1) To answer the title of your post: How to send data from Client controller to Server side?
Normally these two methods on "this" or "c "are used:
- .server.update() - Automatically sends this.data to the server as input
- .server.get() - Sends a custom input object
A third option is via url
2) Looking at some of the threads in this post I'm not sure if you're just trying to download an attachment that is of xls/docx type or if you're trying to just download a xls/docx file based on give table/record information. In the below screencast, is this what you're trying to accomplish?
https://youtu.be/4_pTCOmZc1k
This may not be exactly what you're looking for but I think it has the same concepts where there is input and then it's sent to the server to return some information in order to download a file based on the input. This isn't downloading an attachment though. In this video the widget is downloading either an excel file of the all the incident lists, then a file of a list of incidents based on an encoded query and then finally downloads a single incident record based on the incident number.
This is just a basic MOC up of what I think what is discussed in this thread. Let me know if this is what you're looking for and I'll post the setup.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎12-06-2018 02:25 AM
Hi Chris,
Thank you for the response! My issue to fetch column names and labels has been resolved now.
I am looking forward to inserting the fetched data into docx, xls file and get it to download as per user selection.
I check out the video link, it is somewhat similar to what the requirement is. I have mentioned my requirement below.
My requirement is Onclick of a button the column names and labels should be inserted in the document and it should be downloaded(xls, docx file which depends on user selection) directly.