Technical Articles
Using Smart Field Value Help with normal Input Field
Introduction
With OData and Smart Field, we can using the value help defined by Annotation without Extra JavaScript/XML Code. In some scenario, the page is just too complex to using Fiori Elements or Smart Field.
But the value help from Annotation is convenient and useful feature, so I tried to use value help from OData with Annotation in normal Input Field by creating a “virtual” Smart Field.
View
As the rendering strategy of SAPUI5 is to not add invisible controls to the View tree, so Instead of defining the HBox with property visible= “false”, we define a visible HBox and use CSS to set its visibility to “hidden”. So the “virtual” Smart Field added to this HBox will be invisible.
<Input id="test1" width="10rem" showValueHelp="true" valueHelpRequest="onValueRequest"/>
<HBox width="1px" height="1px" id="invisibleBox" class="invisible">
</HBox>
<Input/>
Controller
In the JavaScript, what we did is mainly three parts:
- Create a Smart Field and bind the OData Model(contains value help annotation) to it
- Fire the “valueHelpRequest” of Smart Field we have created
- Set the selected value from Value Help Dialog to the Input Field
onValueRequest: function() {
/*create the smartfield for using its value help*/
var oSmartFiled = new SmartField({
value:{
path: 'salesOrganization'
}
});
/* Set the selected value to Input Field*/
oSmartFiled.attachChange(() => {
var sValue = oSmartFiled.getValue();
this.getView().byId("test1").setValue(sValue);
oSmartFiled.destroy();
})
/* overwrite the prototype function of this smartfield for adding custom logic to
Promise chain,
Source Code copied from sap.ui.comp.smartfield.SmartField*/
oSmartFiled._createICRenderedDeferred = function () {
var oDef;
oDef = new Deferred();
this._oRenderedWithContext = oDef;
Promise.all([
new Promise(function (fnResolve) {
this.attachInnerControlsCreated(fnResolve);
}.bind(this)),
new Promise(function (fnResolve) {
var oDelegate = {
onAfterRendering: function (oEvent) {
var oFocusCatcher = this._getFocusCatcher(),
oEditControl = this._oControl.edit,
oContent = this.getAggregation("_content");
if (
oEditControl &&
oEditControl.getDomRef() &&
oEditControl.getFocusDomRef() &&
oEditControl === oContent &&
(
!oFocusCatcher ||
!oFocusCatcher.getDomRef()
)
) {
this.removeEventDelegate(oDelegate);
fnResolve();
}
}.bind(this)
};
this.addEventDelegate(oDelegate);
}.bind(this))
]).then(function () {
oDef.resolve();
})
/*Add custom code to the Promise chain for ensure getting the rendered inner
InputField of Smartfield,
and then fire its "ValueHelpRequest" Event to show the Value Help Dialog
*/
.then(
() => {
try{
var sId = oSmartFiled.getId();
var oInput = sap.ui.getCore().byId(`${sId}-input`);
oInput.fireValueHelpRequest();
}catch(reason) {
}
}
);
};
/* Get the ODatamodel which be defined in manefest.json,
bind the ODatamodel to smartfield
add the smartfield to invisible FlexBox
*/
var oSalesModel = this.getOwnerComponent().getModel("salesOData");
var oNewItem = oSalesModel.createEntry("/Z_C_SOHEADER_L2");
oSmartFiled.setModel(oSalesModel);
oSmartFiled.setBindingContext(oNewItem);
var oFlexBox = this.getView().byId("invisibleBox");
oFlexBox.addItem(oSmartFiled);
}
And the result will be:
The value help dialog from Smart Field which opened by normal Input Field
Thank you.
don't know what you are doing....
sounds nonsense to me.