Here is script to add filter buttons to a widget. There will be one button for each items in a dimension and we can filter to a particular item by clicking corresponding button.
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 and select one item in it.
Save the script and refresh widget.
widget.on('processresult', function(se, ev){
ev.result.chart.marginTop= 60
});
var dimension = "[Records.Region]"
var normalState = {
fill: '#EEEDFA',
stroke: '#ADABF6',
r: 3,
style: {
color: '#6D6D6D',
borderWidth : 0
}
},
hoverState = {
fill: '#DDDCF0',
stroke: '#ADABF6',
r: 3,
style: {
color: '#6D6D6D',
borderWidth : 0
}
},
pressedState = {
fill: '#544cf5',
stroke: '#ADABF6',
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)
let widgetFilter = widget.metadata.panels[3].items.find(el => el.jaql.dim == dimension)
$.each(itemlist, function(index, value){
buttonList[index] = chart.renderer.button(value, 10 + (index * 120), 10,
callback,
normalState,
hoverState,
pressedState,
disabledState)
.attr({
zIndex : 10,
height: 15,
width: 100,
'text-align': 'center'
})
.on('click', function() {
widgetFilter.jaql.filter.members[0] = value
widget.refresh();
})
.add();
})
$('.widget-no-result-overlay').css('top', '60px')
chart.buttonList = buttonList
filterItem = widgetFilter.jaql.filter.members[0]
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.
Great. Is there a way to add a filter (dimension with only 2 values) to a numerical widget? Something like two toggle button at the top of a numerical widget. Say "Incoming" "Outgoing" and the numerical widget filters to it when their toggle button is turned on. When both of them are off, then it display to "All".
This is great, I got it working. However, it doesn't seem like I can unclick to select "none". Is that possible?