SAPUI5: Using one sort dialog for two tables
Introduction
Mostly in one application you have to handle more than on tables. Sorting and filtering are properties of an table. It makes sense to create only one dialog and add the filter rows we need for the used table.
This blog gives an instrodukion how to handle this.
Presetting
I have two tables in one view. They are separeted by an IconTabFilter. On each tables there are different columns. On the left side there is an icon for sorting on both tables
table 1:
table 2:
Implementation
Objects Prestes
The implementation is done in only one controller. I create two objects with the name _mSortFieldsVehicle and _mSortFieldsCost in that object the content for the order items are stored. The properties of he objects are:
- name, value, timestamp are the fields in the database
- array vehicleName, vehicleValue, vehicleTimeStamp are the i18n names
- array boolean value are for presetting the sort items
.
.
.
.
return BaseController.extend("controller.Main", {
_mSortFieldsVehicle: {
name: ["vehicleName",true],
value: ["vehicleValue",false],
timestamp: ["vehicleTimeStamp",false]
},
_mSortFieldsCost: {
name: ["costName",true],
price: ["costPrice",false],
timestamp: ["costTimeStamp",false]
},
.
.
.
.
}
Variable Presets
In the onInit Function the variables are presets.
Please see the statements below.
.
.
.
onInit: function() {
this._oVSD = null; // Store the dialog object
this._sSortField = null; // Store the sorted Field
this._bSortDescending = false; // preset the sort direction
this._aValidSortFields = ["name", "value", "timestamp"]; // which fields are valid or search
this._aValidSortFieldsCost = ["name", "price", "timestamp"]; // which fields are valid or search
this._sTableSort = "idVehicle"; // Preset table Vehicle // which table is to sort
this._initViewSettingsDialog(); // initial the dialog
this._oTable = this.byId("tableVehicle"); // Table Vehicle
this._oTableCost = this.byId("tableListCost"); // Table Cost
.
.
.
}
Event Function
On the view on each sort Icon only one function is called. In that function I store the id of the called control in the variable _sTableSort.
The function _setOrderItems() is declared later on.
.
.
.
onSortButtonPressed: function(oEvent) {
var oRouter = this.getRouter();
this._oRouterArgs.query.showDialog = 1;
this._sTableSort= oEvent.getParameter("id"); // Store the called controler ID
this._setOrderItems();
oRouter.navTo("main", this._oRouterArgs);
},
.
.
.
Helper Function
A smal helper function _isTableVehicle give me a clear hint what I check there. For the desicion which table is in function.
The function _isSordFieldValid checks if the sort field is valid for sorting
_isTableVehicle: function() {
return (this._sTableSort.indexOf("idVehicle") > -1);
},
_isSordFieldValid: function(sSortField) {
if (this._isTableVehicle()) {
if (this._aValidSortFields.indexOf(sSortField) > -1) {
return true;
}
} else {
if (this._aValidSortFieldsCost.indexOf(sSortField) > -1) {
return true;
}
}
return false;
},
Add Sort Items
Depends on which table should be sort the _mSorter object is filled with the preset for table 1 (vehicle) or for table 2 (Cost)
_setOrderItems: function() {
var oResourceBundle = this.getResourceBundle();
this._oVSD.removeAllSortItems(); // remove items
// which fields should be sort
var _mSorter = this._isTableVehicle() ? this._mSortFieldsVehicle : this._mSortFieldsCost;
var _loVSD = this._oVSD;
jQuery.each(_mSorter, function(sSortKey, oText) {
_loVSD.addSortItem(new sap.m.ViewSettingsItem({
key: sSortKey,
text: oResourceBundle.getText(oText[0]),
selected: oText[1]
}));
});
},
Init Dialog
The dialog is created here. And at the end the sort items are added in the function setOrder Items
.
.
_initViewSettingsDialog: function() {
var oRouter = this.getRouter();
this._oVSD = new sap.m.ViewSettingsDialog("vsd", {
confirm: function(oEvent) {
var oSortItem = oEvent.getParameter("sortItem");
this._oRouterArgs.query.sortField = oSortItem.getKey();
this._oRouterArgs.query.sortDescending = oEvent.getParameter("sortDescending");
delete this._oRouterArgs.query.showDialog;
oRouter.navTo("main", this._oRouterArgs, true /*without history*/ );
}.bind(this),
cancel: function(oEvent) {
delete this._oRouterArgs.query.showDialog;
oRouter.navTo("main", this._oRouterArgs, true /*without history*/ );
}.bind(this)
});
this._setOrderItems(); // Set the sort Items
},
.
.
.
Route Setting
add the “:?query:” variable to your pattern for you view in which the sorting is done.
.
.
.
"routes": [
{
"pattern": "Policies/{objectId}:?query:",
"name": "main",
"target": [
"main"
]
},
.
.
]
Table Sort
The sort is done in the following method. The descison which table is sort is done on the end of the function. see //Sorting depending on which table is select.
*
* Applies sorting on our table control.
* @param {string} sSortField the name of the field used for sorting
* @param {string} sortDescending true or false as a string or boolean value to specify a descending sorting
* @private
*/
_applySorter: function(sSortField, sortDescending) {
var bSortDescending, oBinding, oSorter;
// only continue if we have a valid sort field
if (sSortField && this._isSordFieldValid(sSortField)) {
// convert the sort order to a boolean value
if (typeof sortDescending === "string") {
bSortDescending = sortDescending === "true";
} else if (typeof sortDescending === "boolean") {
bSortDescending = sortDescending;
} else {
bSortDescending = false;
}
// sort only if the sorter has changed
if (this._sSortField && this._sSortField === sSortField && this._bSortDescending === bSortDescending) {
return;
}
this._sSortField = sSortField;
this._bSortDescending = bSortDescending;
oSorter = new Sorter(sSortField, bSortDescending);
// sync with View Settings Dialog
this._syncViewSettingsDialogSorter(sSortField, bSortDescending);
// Sorting depending on which table is select
if ( this._isTableVehicle() ) {
oBinding = this._oTable.getBinding("items");
} else {
oBinding = this._oTableCost.getBinding("items");
}
oBinding.sort(oSorter);
}
},
Function Chain
The sorting is done after event function onSortButtonPressed is called see Event Function. The routing is invoking the attchPatternMatched where the callback function _onObjectMatched is invoked. If variable showDialog === “1” the dialog will be shown. The sorting is done in the function _applySorter.
onInit: function() {
.
.
var oRouter = this.getRouter();
oRouter.getRoute("main").attachPatternMatched(this._onObjectMatched, this);
}
_onObjectMatched: function(oEvent) {
this._oRouterArgs = oEvent.getParameter("arguments");
this._oRouterArgs.query = this._oRouterArgs["?query"] || {};
if (this._oRouterArgs.query) {
// search/filter via URL hash
//this._applySearchFilter(this._oRouterArgs.query.search);
// sorting via URL hash
this._applySorter(this._oRouterArgs.query.sortField, this._oRouterArgs.query.sortDescending);
// show dialog via url hash
if (this._oRouterArgs.query.showDialog === "1") {
this._oVSD.open();
}
}
},
Result:
It is possible to sort more than one table with only one sort dialog. Here is a short list what is to do.
Offers