Extending a SAPUI5 control
Sometimes SAPUI5 controls does not support a specific use case you run into. For that, an extensibility functionality is provided for all of SAPUI5’s controls.
Extending a control or even creating a new one is a simple task, which will be explained in this step-by-step post. This post will extend the sap.m.Select control, creating an option to add new items to it at runtime. It is divided in the following tasks:
- Create a javascript file to extend the control
- Add new properties and events to control
- Check standard control source code in OpenUI5
- Extend standard control’s function onBeforeRendering + init
- Create function to handle new option
- Extend standard control’s function onSelectionChange
- Add control to the view and test it
If you are on a hurry, you can look at the code from this sample at GitHub and check the behavior of the control at JS Bin.
Feel free to use and enhance this control if it fits your needs 🙂 .
The only requirement to follow this post is having a running SAPUI5 project. If you have not already set up your project, please find helpful content here:
Create an SAPUI5 Application Project – UI Development Toolkit for HTML5 (SAPUI5) – SAP Library
Create a javascript file to extend the control
Start creating a new js file which will be the extension control:
The name of our control will be Select.js.
Add the following code to the control:
jQuery.sap.declare(“<your_project_path>.<your_folder>.Select”);
jQuery.sap.require(“sap.m.Select”);
jQuery.sap.require(“sap.m.SelectRenderer”);
sap.m.Select.extend(“<your_project_path>.<your_folder>.Select”, {
renderer: “sap.m.SelectRenderer”
});
The code above is declaring the control’s name (line 1), requiring the standard controls which will be extended (lines 2 and 3), executing extend function from parent control, and defining the file that will be the renderer.
On this example the renderer will not be extended and the standard will be used.
Until now no changes were made to the control. It would behave exactly like the standard control if instantiated.
Add new properties and events to control
Now create the new properties and events this control needs. This can be done by simply creating a metadata object:
metadata: {
properties: {
“addValueEnabled”: {
type: “boolean”,
defaultValue: true
}
},
events: {
“newValueCreated”: {}
}
}
The addValueEnabled property will be responsible for enabling the new “add” feature. By default it is set to true, and if the user sets it as false the control will behave exactly like the standard sap.m.Select.
In addition, the newValueCreated event will be fired when the user creates a new option.
Also, as a good practice, we are going to create two new constants bellow the metadata object. They will be responsible for the add option’s text and key.
ADD_OPTION_KEY: “__addNewValue”,
ADD_OPTION_TEXT: “Add…”
Check standard control’s source code on OpenUI5 git
Most of the times, extending a control requires extending also some of its functions. For that, it is helpful knowing the standard control’s source code.
The best way to have access to an UI5 control is taking a look at the OpenUI5 git repository.
Extend sap.m.Select standard functions
Looking through the standard control’s source code, it is possible to figure out that some functions need to be extended to support our new feature.
The onBeforeRendering function will place the main code of this extension, where the new option named “Add” will be created and inserted to the select. Besides, the init function will hold a control’s verification property.
init: function() {
// define variable for control initial loading handling
this._bInitialLoading = true;
// execute standard control method
sap.m.Select.prototype.init.apply(this, arguments);
},
onBeforeRendering: function() {
if (this.getAddValueEnabled()) {
// check if “add…” option does not exist yet. if so, create it
if (!this.getItemByKey(this.ADD_OPTION_KEY)) {
// create add value item and add it to select
var oItem = new sap.ui.core.Item({
key: this.ADD_OPTION_KEY,
text: this.ADD_OPTION_TEXT
});
this.insertItem(oItem, 0);
}
// set item index if more than one option and initial loading
if (this._bInitialLoading && this.getItems().length > 1) {
this.setSelectedItem(this.getItems()[1]);
// the “onBeforeRendering” method will only be executed again on new option creation
// further verifications are not necessary
this._bInitialLoading = false;
}
}
// execute standard control method
sap.m.Select.prototype.onBeforeRendering.apply(this, arguments);
}
First it is verified whether the add value feature is enabled in the control. After that, it is verified whether the “Add” option is already created. If not, the “Add” item is created and inserted to the select options. This verification will avoid the creation of multiple “Add” options, because the “onBeforeRendering” function is called always when a new option is created. Note that its key and text are the constants created in step 2.
The next validation checks if the control is in its initial load and if it has any options. In case both sentences are true, the second item (first item after the custom “Add” option) is selected.
Note that on both functions, the standard control’s apply function is being called. This function executes the standard behavior of the control, meaning that both custom and standard content will be executed.
Handling new option
Now it is necessary to create a function to handle the “Add” option. It is a simple item on the select, but will have an special treatment when selected. Instead of just displaying it, a dialog with an input will be shown for the user to add the new value.
It will be necessary to extend the onSelectionChange function from parent control. This function is called when the select value changes and will be enhanced to check whether the selected item is the “Add” option. If the add option is selected a dialog is created with an input to allow the user to enter the new value.
onSelectionChange: function(oControlEvent) {
// get selected item
var oItem = oControlEvent.getParameter(“selectedItem”);
// check if the add value option is enabled and if the key is the ‘add option’ key
if (this.getAddValueEnabled() && oItem.getKey() === this.ADD_OPTION_KEY) {
this._createNewOptionDialog();
}
// execute standard control method
sap.m.Select.prototype.onSelectionChange.apply(this, arguments);
},
_createNewOptionDialog: function() {
// create dialog with input field
var that = this;
var oDialog = new sap.m.Dialog({
title: ‘Add value’,
content: new sap.m.Input({
id: ‘idNewValueInput’
}),
beginButton: new sap.m.Button({
text: ‘Add’,
press: function() {
that._handleNewOption();
oDialog.close();
}
}),
afterClose: function() {
oDialog.destroy();
}
});
oDialog.open();
},
_handleNewOption: function() {
// get new option value
var oInput = sap.ui.getCore().byId(“idNewValueInput”);
var sNewValue = oInput.getValue();
// create new item to be added in select
var oItem = new sap.ui.core.Item({
key: sNewValue,
text: sNewValue
});
// add item to select and set it as selected
this.addItem(oItem);
this.setSelectedItem(oItem);
// fire an event in case the parent object needs to handle this
this.fireNewValueCreated({
value: sNewValue
});
}
When the dialog create button is pressed, the function executed creates a new item, adds it to the select and fires the custom event newValueCreated sending the value as a parameter.
Add control to the view
Using an extension control is as simple as using any other SAPUI5 control.
<mvc:View
xmlns:mvc=“sap.ui.core.mvc”
xmlns=“sap.m”
xmlns:l=“sap.ui.layout”
xmlns:core=“sap.ui.core”
xmlns:custom=“sapui5-control-extension-demo.controls”
controllerName=“sapui5-control-extension-demo.main”
xmlns:html=“http://www.w3.org/1999/xhtml“>
<Page title=“Control extension”>
<content>
<l:VerticalLayout width=“100%”>
<l:content>
<Label text=“Extension Control” />
<custom:Select
width=“50%”
newValueCreated=“handleNewValue”
items=“{/}”>
<core:Item
key=“{CountryId}”
text=“{Name}” />
</custom:Select>
</l:content>
</l:VerticalLayout>
</content>
</Page>
</mvc:View>
It is only necessary to create a new xmlns with the path to the control (or require the control, in case of a JS view) and add it to the view.
The final result is the following: Live demo
Hi Tiago,
I have written a custom control which works fine. However, I am not able to figure out the use of "eventPreventDefault" in events. Whether I set it to true or false it's always executed when the event is triggered.
My understanding was if I set this boolean to true the event handling would be ignored.
Is there a way to dynamically enable or disable the events functions.
For eg. In above example, is it possible to dyamically enable or disable "newValueCreated" function.
Thanks,
Rashmi
Hi Rashmi,
Could you please attach here a code snippet for me to figure out what you are trying to accomplish?
Regards,
Tiago
Please create a new Discussion with your question rather than post a comment to a blog. This is not the right vehicle for asking questions. See the Getting Started link at the top right or view the The Difference between a Discussion, Blog Post, Document and Wiki
Regards, Mike (Moderator)
SAP Technology RIG
Hi Tiago,
I am trying to do something similar, but with the sap.m.SearchField
I would like to extend the search event, so for that purpose, just like you with the onSelectionChange, I am trying to extend the onSearch function.
In the beginning I just put there a simple alert, to check if this works, but unfortunately it is not triggered.
Any idea how to extend it or what I am doing wrong?
Here is the code at the moment:
Regards,
Georgi