Hi,
We are currently working with Servoy 2025.03 and the latest version of the svyPopupFilter module.
When a user clicks the filter icon (fad fa-filter), we display the available filters using:
toolbarFilter.showPopupFilterPicker(_element);
Right now, the filters (which include both custom filters and those coming from the NG Data Grid) appear in their default order. Is there a built-in way or a workaround to sort this list alphabetically?
I tried accessing them via toolbarFilter.getFilters(), but I cannot seem to apply a custom sort order to the popup picker display.
I have already tried retrieving the filters using toolbarFilter.getFilters() and applying a JavaScript .sort() directly to the array before calling showPopupFilterPicker(), but the UI doesn’t seem to reflect the changes (likely because it operates on an internal copy or relies on the creation/column order). Since there is no setFilters() method available, is there any workaround to achieve this?
Thanks in advance!
We did some strange things with the filters, since we tried to present a “logical” Filtermenu with some filters in the “most used” order, some grouped in submenus, like dates - due, created, modified.
To do that we created a presorted array, and used a popmenu that we build from that array, you can just call the function scopes.svyToolbarFilter["onFilterPopupMenuClicked"] with the correct parameters to activate the filter.
It’s a bit to complicated to post, I’ll look into adding that to a nice project, a colleague of mine added more stuff to it (last filter, next filter if skipped back, default filters that always work), saving filters and loading a default filter, I’ll talk to him about it.
Here’s something simpler.
/**
* @param {JSEvent} event the event that triggered the action
* @protected
*/
function onAction_btnShowFilters(event) {
/**
* sort filters by text, change to data_provider if needed
* @param {{dataprovider:String, text:String}} oA
* @param {{dataprovider:String, text:String}} oB
* @return {Number}
* */
function filterSort(oA, oB) {
if (oA.text === oB.text) {
return 0;
} else if (oA.text < oB.text) {
return -1;
} else {
return 1;
}
}
var filterPopupMenu = plugins.window.createPopupMenu();
var columnFilters = toolbarFilter.getFilters();
columnFilters.sort(filterSort)
for (index = 0; index < columnFilters.length; index++) {
menuItem = filterPopupMenu.addMenuItem(columnFilters.dataprovider);
menuItem.text = columnFilter.text;
menuItem.methodArguments = [columnFilter.id, columnFilter.dataprovider];
menuItem.setMethod(scopes.svyToolbarFilter["onFilterPopupMenuClicked"]);
}
}
filterPopupMenu.show(event.getSource());
}
This should (can’t test right now) work, when bound to a button to open a popup-menu, list all filters from a configured filtercomponent (toolbarFilter). The filters are sorted beforehand.
If you need more flexibility you could give a sorted list of dataproviders and get the ids via toolbarFilter.getFilter(<dataprovider>)
1 Like
Hi Robert,
Thanks for your answer. This is the code using all toolbar features, copied from scopes.svyToolbarFilter.createPopupFilterPicker:
function onAction_btnShowFilters(event) {
/**
* sort filters by text, change to data_provider if needed
* @param {{dataprovider:String, text:String}} oA
* @param {{dataprovider:String, text:String}} oB
* @return {Number}
* */
function filterSort(oA, oB) {
if (oA.text === oB.text) {
return 0;
} else if (oA.text < oB.text) {
return -1;
} else {
return 1;
}
}
var /** @type {Array<scopes.svyPopupFilter.AbstractPopupFilter>} */ columnFilters = toolbarFilter.getFilters();
var /** @type {CustomType<window.Popup>} */ filterPopupMenu = plugins.window.createPopupMenu();
var /** @type {CustomType<window.MenuItem>} */menuItem = filterPopupMenu.addMenuItem("title");
menuItem.enabled = false;
menuItem.text = scopes.svyPopupFilter.LOCALE.filterPopupMenu.addFilter;
columnFilters.sort(filterSort)
for (var index = 0; index < columnFilters.length; index++) {
var /** @type {scopes.svyToolbarFilter.Filter} */ columnFilter = columnFilters[index];
var /** @type {RuntimeCheck} */ check = filterPopupMenu.addCheckBox(columnFilter.dataprovider);
check.selected = toolbarFilter['isFilterActive'](columnFilter);
check.text = columnFilter.text||scopes.svyUI.getColumnTitle(scopes.svyDataUtils.getDataProviderRelationName(columnFilter.dataprovider)||toolbarFilter.getFoundSet().getDataSource(),columnFilter.dataprovider);
check.methodArguments = [columnFilter.id, columnFilter.dataprovider]
check.setMethod(scopes.svyToolbarFilter['onFilterPopupMenuClicked']);
}
filterPopupMenu.cssClass = "toolbar-filter-popup";
// cache the latest menu so it can be used in callback
scopes.svyToolbarFilter['latestToolbarFilter'] = toolbarFilter;
filterPopupMenu.show(event.getSource());
}
It’s a pity that this component doesn’t have a direct flag or built-in property to handle the sorting automatically, which would save us from having to write custom sorting logic.
Best regards