Recently, we got a requirement from customer that said the filter function of the ‘sap.m.MulticomboBox’ not easy to use because the default behavior is filter from start per term, just like below.
But customer wants filter works like ‘contains’, so that the items which contains the key words that end user inputted will be filtered out not matter from start or in the middle. Please refer to following screen capture.
We know that ‘MulticomboBox’ already provide the API (setFilterFunction) to change the default filter function. But we got a dozen of comboboxes within a filter bar, it’s too ugly to get all the control instances through “byId” method and set the customized filter function one by one.
So we decided to customize the ‘MulticomboBox’ control. It’s easy, no new property, no new event, no render change. All you need to do is to given a customized filter function through the API (setFilterFunction) with its “init” process. With this slight change, it won’t break any existing functions of original control and compatible with future versions. Please refer code below.
sap.ui.define([
"sap/m/MultiComboBox"
], function (MultiComboBox) {
"use strict";
const CustomMultiComboBox = MultiComboBox.extend("com.sap.***.CustomMultiComboBox", {
renderer: "sap.m.MultiComboBoxRenderer"
});
CustomMultiComboBox.prototype.init = function () {
MultiComboBox.prototype.init.apply(this, arguments);
this.setFilterFunction( (sTerm, oItem) => {
let sItemText = oItem.getText().toLowerCase(),
sSearchTerm = sTerm.toLowerCase();
return sItemText.indexOf(sSearchTerm) > -1;
});
};
return CustomMultiComboBox;
});
And then, you could use this ‘CustomMultiComboBox‘ control with your XML view directly. Simple and clear.
<fb:FilterGroupItem groupName="__$INTERNAL$" name="idFilterGroupItemCompany"
label="{i18n>taskFilterByCompanyLabelNew}" visibleInFilterBar="true">
<fb:control>
<tm:CustomMultiComboBox id="companyComboBox" width="380px"
selectionChange="onComboBoxSelectionChanged;onCompanySelectionChanged"
ariaLabelledBy="idFilterGroupItemCompany" busyIndicatorDelay="0" busy="false"
items="{path:'chartFilter>/companyFilter',sorter:{path:'text',comparator:'.sorter.alphabetSorterWithPriority'},templateShareable:false}">
<core:Item key="{chartFilter>id}"
text="{path: 'chartFilter>text', type: '.UnescapedString'}" />
</tm:CustomMultiComboBox>
</fb:control>
</fb:FilterGroupItem>
<fb:FilterGroupItem groupName="Additional" groupTitle="{i18n>AdditionalGroupName}"
name="idFilterGroupItemSolutionProcess" label="{i18n>taskFilterBySolutionProcessLabel}"
visibleInFilterBar="{= !!${calmContext>/isFromPTMRequirements}}">
<fb:control>
<tm:CustomMultiComboBox id="solutionProcessComboBox" width="380px"
selectionChange="onComboBoxSelectionChanged"
ariaLabelledBy="idFilterGroupItemSolutionProcess" busyIndicatorDelay="0"
busy="false" items="{path:'chartFilter>/solutionProcessFilter',
sorter:[{path: 'version_sequence', group: '.formatter.solutionProcessGroupFormatter'}, {path: 'text'}],
templateShareable:false, groupHeaderFactory: '.formatter.getSolutionProcessGroupHeader'}">
<core:Item key="{chartFilter>id}" text="{chartFilter>text}" />
</tm:CustomMultiComboBox>
</fb:control>
</fb:FilterGroupItem>
Wrap up: Through this real case, I want to show you that with a little customization with control could make your code much simple. Front-end developers may feel it hard to customize control, sometimes, yes. But it not always true, that depends the complexity about your requirement. Raise a feature request for control team also not a good way to solve your problem right now, it takes time. So custom control is the best solution sometimes. I will try to record all the cases of customization control with our project (add new property, new event, change render, etc). If you not familiar with the basis of custom control, please refer to the section of UI5 doc. And please feel free to share your option, thanks!