- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-28-2019 04:03 AM
Hi,
TL;DR:
Is there a way to catch the selected value of a dashboard breakdown and pass it to a dynamic content block in the same dashboard?
I'm building a dashboard that includes both Performance Analytics widgets as well as standard reporting widgets.
These widgets are based on the task table. And I need to be able to sort their contents by task type.
With PA widgets this is no problem. I have a scripted breakdown that matches the value of sys_class_name in the task table to the sys_id of sys_db_object.
I then added a dashboard breakdown which filters all the PA widgets based on this scripted breakdown.
For normal reporting widgets it's a bit more complicated. Since dashboard breakdowns can only act as interactive filters for reference fields or choice lists in the source data table, the dashboard breakdown can not be used to filter these reports by task type, as the field sys_class_name in the task table is neither a reference field nor a choice list.
For this I used I built a jelly content block that implements the DashboardMessageHandler class. Basically I copied the script provided by Arnoud Kooi in this thread: https://community.servicenow.com/community?id=community_question&sys_id=70a21e73dbcb6f40b1b102d5ca96...
Sp this content block can filter the reporting widgets, while the dashboard breakdown can filter the PA widget. Now I would like to synchronize these. Meaning that the choice made in the dashboard breakdown should be passed to the dynamic content block. The other way around is not needed.
Can anyone help me understand this better, basically all I need to know is how I cant assign the value of the choosen breakdown to a variable in the content block.
Thanks in advance!
Solved! Go to Solution.
- Labels:
-
Scripting and Coding
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-28-2019 12:45 PM
1) Be careful with a scripted breakdown running a query to get the sys_class. Performance is typically much better using a view to join to sys_db_object and skip the scripting.
2) While this may not be future proof (since it isn't documented), try looking at the value:
window.SNC.PA.breakdown_element
and subscribing to the event fo the change:
SNC.canvas.eventbus.subscribe('setBreakdownParams', <callbackfunction>);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-28-2019 12:45 PM
1) Be careful with a scripted breakdown running a query to get the sys_class. Performance is typically much better using a view to join to sys_db_object and skip the scripting.
2) While this may not be future proof (since it isn't documented), try looking at the value:
window.SNC.PA.breakdown_element
and subscribing to the event fo the change:
SNC.canvas.eventbus.subscribe('setBreakdownParams', <callbackfunction>);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-29-2019 05:53 AM
Hi Adam, and thanks for the info.
I really should do a join instead of a scripted breakdown, but it would require recollecting a whole bunch of scores and redefinining so many indicators. Sometime in the future, when I have time.
When I try to use window.SNC.PA it keeps giving me errors in the console that the property "PA" cannot be read from "undefined". I'm guessing this is because I don't have responsive dashboards turned on.
I did try the backwards compability-fix found here:
https://developer.servicenow.com/app.do#!/event/creatorcon18/CCW1161/creatorcon_18_CCW1161_create_dy...
Ie this:
window.SNC = window.SNC || {};
window.SNC.canvas = window.SNC.canvas || {};
window.SNC.PA = window.SNC.PA || {};
window.SNC.PA.new_canvas = window.SNC ${AND} SNC.dashboards ${AND} SNC.canvas ${AND} SNC.canvas.isGridCanvasActive;
But as far as I can tell it just defines an empty object. When I try to read that in my script it just gives me "undefined". I'm guessing because it's empty. I can't find much info about window.SNC on google unfortunately.
I did get it working though. I used the page URL to get the sys_id of the element. I would prefer reading a property but what I came up with worked for now:
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<g:evaluate var="jvar_id" jelly="true">
var resultArr=[];
//Read the page URL which will contain the sysID of the breakdown
var URL;
URL = gs.action.getGlideURI().toString();
//Find the part of the string containing the SYSID
var index;
index = URL.indexOf('sysparm_element_value=');
if(index ==-1) {
var obj = {
name: 'none',
label: 'none',
};
resultArr.push(obj);
};
else {
var preString;
preString = "sysparm_element_value=";
var searchString;
searchString = "&";
var preIndex;
preIndex= URL.indexOf(preString);
var searchIndex;
searchIndex = preIndex + URL.substring(preIndex).indexOf(searchString);
var finSYSID;
finSYSID = URL.substring(preIndex+22, searchIndex);
//Now search sys_db_object for the name based on the found sysID
var grTable = new GlideRecord('sys_db_object');
grTable.addQuery('sys_id',finSYSID);
grTable.query();
while(grTable.next()) {
var name = grTable.name.getDisplayValue();
var label = grTable.label.getDisplayValue();
//Create object containing the label and name. Only name will be needed for the filter but the label might be used later for displaying filter info to the user
var obj = {
name: name,
label: label,
};
resultArr.push(obj);
};
};
//The array should only contain one object, return the name property of that
returnObject = resultArr[0].name;
returnObject;
</g:evaluate>
<script>
//This is the name returned from the evaluate, places in a variable
var elementName = "${jvar_id}";
console.log('6f7k this is the elementName: '+elementName);
//Initiate the dashboardmessagehandler
var dbh = new DashboardMessageHandler("filter_tasktype");
//Defined the function to apply the filter, the first part is the table the reporting widgets are based on, in this case a database view. The second part is the field with the variable containing the name.
function publishFilter() {
dbh.publishFilter('u_sll_tasks_combined_improved','task_sys_class_name='+elementName);
};
//Define a function to remove the filter. It' wont be used in this case but might as well have it for future cases
function clearFilter() {
dbh.removeFilter();
};
//Define a function to reload a certain report graph that did not automatically refresh when the filter was applied.
function reloadGraph() {
//Use queryselector to find the refresh link in the grapgh, in this case the report was placed in the div dropzone2
var foundElement = document.querySelector("#dropzone2");
foundLink = foundElement.querySelector("a.icon-refresh");
foundLink.click();
}
//As we change the dashboard breakdown, the page reloads. At that point we apply the interactive filter
addLoadEvent(function() {
if(elementName !='none') {
publishFilter ();
setTimeout(function(){
reloadGraph();
}, 1000);
}
});
</script>
</j:jelly>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-13-2022 12:35 PM
You can use this to get the sys_id of your breakdown source filter. window.SNC.canvas.interactiveFilters.defaultValues