问题
I am trying to create a combo box with a list of countries in SAP UI5.
I have created a combo box and have created dynamic list of some countries, but to create more than 100 countries, the only easy way is to create a JSON file of countries and then populate in Controller.js.
I tried to create a JSON file but I am unsure whether I have to store it under model folder or root.
What changes do I have to make in my XML view and controller, and where should I attach countries.json
file?
回答1:
You are looking at something called as "Aggregation Binding" Aggregation Binding in XML views
Here is an example to refer to which explains
- How to create a model using data from json file
- How to Bind model data to the XML view control(you have to bind comboBox instead of table)
How to bind json data model to an XML view
Let me know if this helps.
回答2:
Maybe you don't need to create the countries.json
file at all :)
As UI5 leverages Common Locale Data Repository (CLDR) internally and provides the data via sap.ui.core.LocaleData
API, which includes language names, country names, currency names, singular/plural modifications, and more..
A list of supported regions for the locale data are stored in a JSON format here. In one of those files, if you look at the property "territories"
, you'll see that the country names are listed among them. You can filter every irrelevant territory out that is not considered a country, and then bind the rest in the items
aggregation of the combo box.
Demo
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/core/Locale",
"sap/ui/core/LocaleData",
"sap/ui/model/json/JSONModel",
"sap/ui/core/mvc/XMLView",
], function(Locale, LocaleData, JSONModel, XMLView) {
"use strict";
XMLView.create({
definition: `<mvc:View xmlns:mvc="sap.ui.core" xmlns="sap.m"
height="100%"
displayBlock="true">
<ComboBox class="sapUiTinyMargin"
width="15rem"
placeholder="Select a country.."
filterSecondaryValues="true"
showSecondaryValues="true"
items="{
path: '/',
templateShareable: false,
key: 'code',
sorter: { path: 'name' }
}">
<core:ListItem xmlns:core="sap.ui.core"
key="{code}"
text="{name}"
additionalText="{code}" />
</ComboBox>
</mvc:View>`,
models: createCountryModel(getCountries()),
}).then(view => view.placeAt("content"));
function createCountryModel(countries, sizeLimit = 300) {
const model = new JSONModel(countries);
model.setSizeLimit(sizeLimit);
model.setDefaultBindingMode("OneWay");
return model;
}
function getCountries() {
const territories = getTerritories();
return extractCountriesFrom(territories, byCustomCheck());
}
function getTerritories(localeId) {
const currentConfig = sap.ui.getCore().getConfiguration();
const locale = localeId ? new Locale(localeId) : currentConfig.getLocale();
const localeData = new LocaleData(locale);
return localeData.getTerritories(); // includes country names
}
function extractCountriesFrom(territories, customCheck = () => true) {
const isValidCountry = createCountryCheck(customCheck);
const toObject = code => Object.freeze({
code: code,
name: territories[code],
});
const countryObjects = Object.keys(territories)
.filter(isValidCountry)
.map(toObject);
return Object.freeze(countryObjects);
}
function createCountryCheck(customCheck, obviouslyNotCountries = [
"EU", // "European Union"
"EZ", // "Eurozone"
"UN", // "United Nations"
"ZZ", // "Unknown Region"
]) {
return territoryCode => territoryCode.length == 2
&& !obviouslyNotCountries.includes(territoryCode)
&& customCheck(territoryCode);
}
function byCustomCheck() { // returns a function that returns boolean
// E.g.: list of sanctioned countries you want to exclude
const list = [
"AF",
"KP",
"IR",
// ...
];
return countryCode => !list.includes(countryCode);
}
}));
<script id="sap-ui-bootstrap" src="https://ui5.sap.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core, sap.m"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-async="true"
data-sap-ui-compatversion="edge"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>
As you can see in the example, the ComboBox is successfully populated with the countries. When a new LocaleData
instance is created, a request is sent immediately (currently via sync XHR) to get the data which are translated in the language that UI5 detects from the client settings. If no language could be detected, the en.json file will be retrieved.src
The above approach has the following advantages:
- No need to create and maintain a separate "country" list. ✔️
- Multilingual support ✔️
- Reusability ✔️ - When UI5 tries to fetch the same locale data file, which is the case when e.g. a Calendar is used, the browser can serve the file quickly from the cache since the same file was already fetched before.
Note
When creating a JSONModel
to store more than 100 country names, keep in mind to increase the size limit as well. The current default limit is 100
.
来源:https://stackoverflow.com/questions/50916889/create-country-list-from-json