Stacked Bar Chart As Filter Indicators
In this post, we will show how to override the default behavior of the stacked bar chart widget. This will display a block (sized based on the value) for each break by category, and allows filter selection on click of a block.

Create a Sisense bar chart widget that contains a dimension for Break By as well as the value. To make for a cleaner look, I suggest disabling the x-axis and y-axis formatting and sticking with the Stack 100 Bar type.

I also suggest making sure to disable the dashboard level filter for the Break By dimension, otherwise any selection will slice the data to only the selected member.

Once configured, save the widget, then come back to the widget editor and edit the script. Take note of the designer options at the top, for deciding on a font color, the height of each bar (in pixels) as well as the sort order of the bars.
/*
Welcome to your Widget's Script.
To learn how you can access the Widget and Dashboard objects, see the online documentation at http://developer.sisense.com/pages/viewpage.action?pageId=557127
*/
// Designer Options
var fontColor = '#ffffff',
barHeight = 75,
reverseOrder = false;
widget.on('render', function(widget,args){
// Get the formatting mask
var mask = $$get(widget.metadata.panel('values').items[0], 'format.mask', null);
// Get the sisense formatter
var $filter = prism.$injector.get('$filter')('numeric');
// Custom formatter function
function customFormatter(options){
// Center the labels
options.align = "center";
// Change the color
options.style.color = fontColor;
// Change the label text
var myValue = $filter(this.y,mask);
// Return both the break by name + formatted value
return this.series.name + '<br />' + myValue;
}
// Get a reference to the break by's metadata item
var metadata = widget.metadata.panel('break by').items[0].jaql;
// Define the options for filtering
var filterOptions = {
'save': true,
'refresh': true,
'unionIfSameDimensionAndSameType':false
};
// Custom Click Handler
function customClick(event){
// Look for any existing filter
var matchingFilters = widget.dashboard.filters.$$items.filter(function(f){
return f.jaql.dim == metadata.dim;
})
// Get the existing filter's selection
var existingMember = matchingFilters.length > 0 ? $$get(matchingFilters[0], 'jaql.filter.members', []) : [];
// Get the clicked break by member
var thisMember = this.series.name;
// If there is already a selection, is it the same as what was just clicked?
var sameSelection = existingMember.length > 0 ? (existingMember[0] == thisMember) : false;
// Generate the filter jaql
var jaql = {
'jaql': $$.object.clone(metadata, true)
}
// Set the selection
if (sameSelection) {
// New Selection, select this member
jaql.jaql.filter = {
'all': true
}
} else {
// Same selection, go back to include all
jaql.jaql.filter = {
members: [thisMember]
}
}
// Save the filter to the dashboard
widget.dashboard.filters.update(jaql,filterOptions);
};
// Override the value label formatter
widget.queryResult.plotOptions.series.dataLabels.formatter = customFormatter;
// Loop through each series
widget.queryResult.series.forEach(function(series){
// Loop through each data point
series.data.forEach(function(point){
// Override the click handler, for each data point
point.events = {
click: customClick
};
})
})
// Increase the bar width
widget.queryResult.plotOptions.series.pointWidth = barHeight;
// Display sort order
widget.queryResult.yAxis[0].reversedStacks = reverseOrder;
widget.queryResult.legend.reversed = reverseOrder;
})
Updated 03-02-2023
intapiuser
Admin
Joined December 15, 2022