If we want to do a more complex logic for formatting properties of our data model, we can also write a custom formatting function. We will now add a localized status with a custom formatter, because the status in our data model is in a rather technical format.
A status is now displayed with a custom formatter
You can access the live preview by clicking on this link: 🔗 Live Preview of Step 22.
We will add three new entries to the resource bundle that reflect translated status texts ‘New’, ‘In Progess’, and ‘Done’. We will use these texts to format the status values ‘A’, ‘B’, and ‘C’ of our invoices when displayed in the invoice list view.
...
# Invoice List
invoiceListTitle=Invoices
invoiceStatusA=New
invoiceStatusB=In Progress
invoiceStatusC=Done
We will create a formatter function to transform status codes into user-friendly text labels.
We create a file named formatter.?s
within the model
folder. This module contains the statusText
function which takes a status code as input, retrieves the corresponding descriptive text from the resource bundle, and returns it. If no matching text is found in the resource bundle, or if the resource bundle can’t be found, the function returns the original status code itself.
import ResourceBundle from "sap/base/i18n/ResourceBundle";
import Controller from "sap/ui/core/mvc/Controller";
import ResourceModel from "sap/ui/model/resource/ResourceModel";
export default {
statusText: function (this: Controller, status: string): string | undefined {
const resourceBundle = (this?.getOwnerComponent()?.getModel("i18n") as ResourceModel)?.getResourceBundle() as ResourceBundle;
switch (status) {
case "A":
return resourceBundle.getText("invoiceStatusA");
case "B":
return resourceBundle.getText("invoiceStatusB");
case "C":
return resourceBundle.getText("invoiceStatusC");
default:
return status;
}
}
};
sap.ui.define([], function () {
"use strict";
return {
statusText: function (status) {
const resourceBundle = this?.getOwnerComponent()?.getModel("i18n")?.getResourceBundle();
switch (status) {
case "A":
return resourceBundle.getText("invoiceStatusA");
case "B":
return resourceBundle.getText("invoiceStatusB");
case "C":
return resourceBundle.getText("invoiceStatusC");
default:
return status;
}
}
};
});
This time we do not extend from any base object but just return an object with our formatter
functions inside.
The new formatter
file is placed in the model folder of the app, because formatters are working on data properties and format them for display on the UI.
📌 Important:
In the above example,this
refers to the controller instance as soon as the formatter gets called. We access the resource bundle via the component usingthis.getOwnerComponent().getModel()
instead of usingthis.getView().getModel()
. The latter call might returnundefined
, because the view might not have been attached to the component yet, and thus the view can’t inherit a model from the component.
Additional Information:
sap.ui.core.mvc.Controller#getOwnerComponent
.sap.ui.core.mvc.Controller#onInit
.We add the ObjectStatus
control to our ObjectListItem
using the firstStatus
aggregation. We bind the control not only to the technical status but also to the statusText
function in our formatter to displaly the human-readable texts per invoice we specified in our resource bundle.
<mvc:View
controllerName="ui5.walkthrough.controller.InvoiceList"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc">
<List
headerText="{i18n>invoiceListTitle}"
class="sapUiResponsiveMargin"
width="auto"
items="{invoice>/Invoices}" >
<items>
<ObjectListItem
core:require="{
Currency: 'sap/ui/model/type/Currency'
}"
title="{invoice>Quantity} x {invoice>ProductName}"
number="{
parts: [
'invoice>ExtendedPrice',
'view>/currency'
],
type: 'Currency',
formatOptions: {
showMeasure: false
}
}"
numberUnit="{view>/currency}"
numberState="{= ${invoice>ExtendedPrice} > 50 ? 'Error' : 'Success' }">
<firstStatus>
<ObjectStatus
core:require="{
Formatter: 'ui5/walkthrough/model/formatter'
}"
text="{
path: 'invoice>Status',
formatter: 'Formatter.statusText.bind($controller)'
}"
/>
</firstStatus>
</ObjectListItem>
</items>
</List>
</mvc:View>
We used the require
attribute with the namespace URI sap.ui.core
, for which the prefix core
is already defined in our XML view. This allows us to write the attribute as core:require
. We then added our custom formatter module to the list of required modules and assigned it the alias Formatter
, making it available for use within the view.
in the ObjectStatus
control we defined our alias Formatter
that holds our formatter functions, so we can access our function by Formatter.statusText
. When called, we want the this
context to be set to the controller instance of the current view. To achieve this, we used .bind($controller)
.
Next: Step 23: Filtering
Previous: Step 21: Expression Binding
Related Information
Formatting, Parsing, and Validating Data
Require Modules in XML View and Fragment
API Reference: sap.ui.base.ManagedObject.PropertyBindingInfo