We already have a script to add filter buttons in a widget. Here is an upgraded version of the script which will add another button 'All' to select all items in the filter. Also added functionality to unselect a filter. For example, if you click on an already selected button, it will get unselected and display all items.
Steps:
Create a Line/Column/Bar/Area/Pie chart
Add below script to the widget and update the variable 'dimension' with name of dimension in the format "[Table Name.Column Name]". Items in this field will be displayed as button. Add the same column in widget filter pane.
Save the script and refresh widget.
widget.on('processresult', function(se, ev){
ev.result.chart.marginTop= 60
});
var dimension = "[Records.Region]"
var normalState = {
fill: '#fcd4d2',
stroke: '#cc4e45',
r: 3,
style: {
color: '#6D6D6D',
borderWidth : 0
}
},
hoverState = {
fill: '#d6665e',
stroke: '#cc4e45',
r: 3,
style: {
color: '#6D6D6D',
borderWidth : 0
}
},
pressedState = {
fill: '#c9483e',
stroke: '#cc4e45',
r: 3,
style: {
color: '#FFFFFF',
borderWidth : 0
}
},
disabledState = {
fill: '#EEEDFA',
stroke: '#ADABF6',
r: 5,
style: {
color: '#6D6D6D',
borderWidth : 0
}
},
callback = function () {
}
widget.on("domready", function(w){
let chart = w.chart[0][Object.keys(w.chart[0])[0]].hc
let items = getItemList(w).values;
//items.length = 10
let itemlist = Array.from(items, x=>x[0].data)
let buttonList = new Array(itemlist.length + 1)
let widgetFilter = widget.metadata.panels[3].items.find(el => el.jaql.dim == dimension)
$.each(itemlist, function(index, value){
buttonList[0] = chart.renderer.button('All', 10, 10,
callback,
normalState,
hoverState,
pressedState,
disabledState)
.attr({
zIndex : 10,
height: 15,
width: 80,
'text-align': 'center'
})
.css({width: '116px'})
.on('click', function() {
widgetFilter.jaql.filter = {
"explicit": false,
"multiSelection": true,
"all": true
}
widget.refresh();
})
.add();
})
$.each(itemlist, function(index, value){
buttonList[index+1] = chart.renderer.button(value, 10 + ((index+1) * 100), 10,
callback,
normalState,
hoverState,
pressedState,
disabledState)
.attr({
zIndex : 10,
height: 15,
width: 80,
'text-align': 'center'
})
.css({width: '116px'})
.on('click', function() {
if( widgetFilter.jaql.filter.members && widgetFilter.jaql.filter.members[0] && widgetFilter.jaql.filter.members[0] == value)
{
widgetFilter.jaql.filter = {
"explicit": false,
"multiSelection": true,
"all": true
}
}
else
{
widgetFilter.jaql.filter = {
"explicit": true,
"multiSelection": true,
"members": [
value
]
}
}
widget.refresh();
})
.add();
})
$('.widget-no-result-overlay').css('top', '60px')
chart.buttonList = buttonList
if( widgetFilter.jaql.filter.members && widgetFilter.jaql.filter.members[0])
filterItem = widgetFilter.jaql.filter.members[0]
else
filterItem = 'All'
currentButton = buttonList.find(el=>el.text.textStr == filterItem)
highlightButton(currentButton, chart)
});
function highlightButton(clickedButton, chart){
chart.buttonList.forEach(button => {
if (button.text.textStr !== clickedButton.text.textStr) {
button.setState(0)
}
else{
button.setState(2)
}
})
}
function runHTTP(jaql) {
// Use $internalHttp service if exists
const $internalHttp = prism.$injector.has("base.factories.internalHttp") ?
prism.$injector.get("base.factories.internalHttp") : null;
// Ajax configurations
const ajaxConfig = {
url: "/api/datasources/" + encodeURIComponent(jaql.datasource.title) + "/jaql",
method: "POST",
data: JSON.stringify(jaql),
contentType: "application/json",
dataType: "json",
async: false
};
// Use $internalHttp service for v8.0.1+
// else use default ajax request
const httpPromise = $internalHttp ? $internalHttp(ajaxConfig, true) : $.ajax(ajaxConfig);
// Return response
return httpPromise.responseJSON;
};
function getItemList(widget) {
const query = {
"datasource": widget.datasource.title,
"metadata": [
{
"jaql": {
"dim": dimension,
"filter": {
"explicit": false,
"multiSelection": true,
"all": true
}
}
}
]
};
return runHTTP(query);
}
Note: If there are more items in the column, all buttons may not be displayed as there won't be enough space to display all of them.
Here's a slightly modified version of the script that enables multi-select functionality. The original script essentially treated the buttons as a radio selection, with only one filter value being active at a time. I asked ChatGPT for help with modifying the code to support multiple selections. Now it'll treat each button like a toggle, so you can have multiple values being filtered at the same time. Clicking the "All" button still works as expected, and clears all selections.
widget.on('processresult', function(se, ev){
ev.result.chart.marginTop = 60;
});
var dimension = '[Records.Region]';
var normalState = {
fill: '#fcd4d2',
stroke: '#cc4e45',
r: 3,
style: {
color: '#6D6D6D',
borderWidth: 0
}
};
var hoverState = {
fill: '#d6665e',
stroke: '#cc4e45',
r: 3,
style: {
…
Exactly what we needed. Thank you so much!