Урок 9. SapUI5: Форматирование (Formatter). Сортировка и фильтрация.

Продолжим знакомиться с особенностями SapUI5. Сегодня посмотрим возможности форматирования данных, сортировку и фильтрацию данных модели. Поехали!

Форматирование (Formatter).

Форматирование даты в SapUI5:

Часто возникает необходимость вывести дату. И не просто вывести, а вывести дату в определенном формате.
Возьмем наш предыдущий пример https://github.com/kannade/DataBinding_sapui5:
дата formatter

Сделать это можно при помощи нативных (встроенный в стандартный функционал SapUI5) средств форматирования, прописав formatOptions:

/DataBinding_sapui5/blob/master/webapp/view/Formatting.view.xml
1
2
3
4
5
6
7
8
9
10
11
<label text="Short"></label>
<text text="{ path: '/dateStr', type: 'sap.ui.model.type.Date', formatOptions: { style: 'short', source: { pattern: 'yyyy.MM.dd' } } }"></text>
 
<label text="Medium"></label>
<text text="{ path: '/dateStr', type: 'sap.ui.model.type.Date', formatOptions: { style: 'medium', source: { pattern: 'yyyy.MM.dd' } } }"></text>
 
<label text="Long"></label>
<text text="{ path: '/dateStr', type: 'sap.ui.model.type.Date', formatOptions: { style: 'long', source: { pattern: 'yyyy.MM.dd' } } }"></text>
 
<label text="Full"></label>
<text text="{ path: '/dateStr', type: 'sap.ui.model.type.Date', formatOptions: { style: 'full', source: { pattern: 'yyyy.MM.dd' } } }"></text>

Параметры для форматирования даты:

  • Шаблон даты (format):

    Используя определенные символы, мы можем форматировать дату в необходимый нам вид.

    Символы: Век (G), Год (y/Y), Квартал (q/Q), Месяц (M/L), Неделя (w/W), День недели (E/c), День (d/D), Час (h/H/k/K), минута (m), секунда (s), Временная зона (z/Z/v/V/O/X/x).

    Полный список — https://openui5.hana.ondemand.com/#/topic/91f2eba36f4d1014b6dd926db0e91070.

    Пример:

    1
    2
    3
    4
    5
    
    var oFormat = sap.ui.core.format.DateFormat.getInstance({
    	format: "yMMMd"
    });
     
    oFormat.format(new Date()); //В немецкой локализации результат будет "29. Jan. 2017"; в английской "Jan 29, 2017"
  • pattern — строгий шаблон даты на основе заданного шаблона.

    Пример:

    1
    2
    3
    4
    5
    6
    
    var oDateFormat = sap.ui.core.format.DateFormat.getDateInstance({
        pattern: "EEE, MMM d, yyyy"});
     
    var oNow = new Date();
    oDateFormat.format(oNow); //результат "Thu, Jan 29, 2017"
  • Style. Может принимать значения empty, short, medium или long.
    Если pattern или format установлен, то Style будет игнорироваться. См. наш пример выше.
  • Относительный формат даты.
    relativeRange: диапазон дней, используемый для относительного форматирования. Если relativeRange равен 6, это означает, что только даты не позднее 6 дней будут отформатированы относительно.

    relativeScale: относительная шкала. Выбирается в зависимости от разницы между данной датой и настоящим временем.

    Пример:

    /DataBinding_sapui5/blob/master/webapp/view/Formatting.view.xml
    1
    2
    
    <label text="Относительное время"></label>
    <text text="{ path: '/date', type: 'sap.ui.model.type.Date', formatOptions: { relative: true, relativeScale: 'auto' } }"></text>
  • Если параметр interval установлен как true, DateFormat способен отформатировать две даты в качестве интервала.

    Пример:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    var oFormat = sap.ui.core.format.DateFormat.getInstance({
    	format: "yMMMd",
    	interval: true
    });
    var oDate1 = new Date(2017, 3, 11);
    var oDate2 = new Date(2017, 4, 11);
    oFormat.format([oDate1, oDate2]);  
    // В немецкой локализации результат будет "11. Apr. – 11. Mai 2017"; 
    // В английской локализации результат будет "Apr 11 – May 11, 2017"

Форматирования чисел в SapUI5:

Или вывести в необходимом формате число:
формат фисла

/DataBinding_sapui5/blob/master/webapp/view/Formatting.view.xml
1
2
3
4
5
6
7
8
<label text="С группировкой разрядов"></label>
<text text="{ path: '/floatVal', type: 'sap.ui.model.type.Float', formatOptions: { groupingEnabled: true, groupingSeparator: ',', decimalSeparator: '.' } }"></text>
 
<label text="2 десятичных разряда"></label>
<text text="{ path: '/floatVal', type: 'sap.ui.model.type.Float', formatOptions: { maxFractionDigits: 2, groupingEnabled: false, groupingSeparator: ',', decimalSeparator: '.' } }"></text>
 
<label text="C ведущими нулями"></label>
<text text="{ path: '/floatVal', type: 'sap.ui.model.type.Float', formatOptions: { minIntegerDigits: 20, groupingEnabled: false, groupingSeparator: ',', decimalSeparator: '.' } }"></text>
  • minIntegerDigits: минимальное количество целых цифр. Если в числе меньше целочисленных цифр, чем указанно в данном параметре, то в начало будут добавлены нули. Смотрите пример выше «C ведущими нулями».
  • maxIntegerDigits: максимальное количество целых цифр. Если в числе целых чисел больше, чем указанно в данном параметре, то все целые цифры будут заменены на «?».
  • minFractionDigits: минимальное количество цифр в дробной части числа. Если в числе меньше дробных цифр, чем значение данного параметра, то будут добавлены нули.
  • maxFractionDigits: максимальное количество цифр в дробной части числа. Если в числе больше дробных цифр, чем значение данного параметра, то эти цифры будут исключены, а наименьшая значащая цифра округляется (вычисляется с использованием roundingMode).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    var oLocale = new sap.ui.core.Locale("en-US");
    var oFormatOptions = {
        minIntegerDigits: 3,
        maxIntegerDigits: 5,
        minFractionDigits: 2,
        maxFractionDigits: 4
    };
     
    var oFloatFormat = sap.ui.core.format.NumberFormat.getFloatInstance(oFormatOptions, oLocale);
    oFloatFormat.format(1.1); // результат - 001.10oFloatFormat.format(1234.567); // результат - 1,234.567oFloatFormat.format(123456.56789); // результат - ??,???.5679
  • decimals: число дробных цифр.
  • precision: количество цифр, используемых для отображения числа. Например, если установить данный параметр = 5, то итоговое число может быть 1.3456 или 134.45.
  • shortDecimals: количество цифр в сокращенном числе. Если параметр style не задан как short, то используется значение из decimals.
1
2
3
4
5
6
7
8
9
10
var oLocale = new sap.ui.core.Locale("en-US");
var oFormatOptions = {
    style: "short",
    decimals: 1,
    shortDecimals: 2
};
 
var oFloatFormat = sap.ui.core.format.NumberFormat.getFloatInstance(oFormatOptions, oLocale);
oFloatFormat.format(1234.56); // результат - 1.23K (применяется параметр shortDecimals)oFloatFormat.format(123.456); // результат - 123.5 (число не "короткое", применяется параметр decimals)

Дополнительные параметры для форматирования чисел:

  • groupingEnabled определяет, будут ли целая часть числа разделена на группы, которые разделены параметром groupingSeparator.
  • groupingType определяет тип группировки. Здесь можно установить либо Arabic, либо Indian.
  • groupingSeparator определяет разделитель группировки.
  • decimalSeparator определяет символ десятичной точки.
  • groupingSize размер групп.
  • groupingBaseSize определяет определенный размер группы, если она отличается от размера группировки (например, Indian).
  • plusSign — знак плюса.
  • minusSign — знак минуса.
  • roundingMode параметр, отвечающий за то, как будут округляться числа. округления для отбрасывания цифр после максимальных десятичных цифр, определяемых maxFractionDigits или десятичными знаками. Округление будет применяться только в том случае, если значение форматирования имеет номер типа.


Возможные значения параметра roundingMode, клик для увеличения картинки.

Подробней про все параметры читаем тут — https://openui5.hana.ondemand.com/#/api/sap.ui.core.format.NumberFormat.

Форматирования «ценовых» чисел:

  • showMeasure — показывать единицу измерения числа.
  • currencyCode — использовать код или символ, только при установке showMeasure в true.
  • currencyContext определяет, какой шаблон используется для форматирования номера валюты. Может использоваться либо standard, либо accounting.

Пример:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var oLocale = new sap.ui.core.Locale("en-US");
var oFormatOptions = {
    showMeasure: true,
    currencyCode: false,
    currencyContext: 'standard'
};
 
var oCurrencyFormat = sap.ui.core.format.NumberFormat.getCurrencyInstance(oFormatOptions, oLocale);
oCurrencyFormat.format(1234.567, "USD"); // результат US$1,234.57 (дробная часть по умолчанию = 2 для USD)oCurrencyFormat.format(1234.567, "JPY"); // результат JP¥1,235 (дробная часть по умолчанию = 0 для JPY) 
oFormatOptions = {
    showMeasure: true,
    currencyCode: true,
    currencyContext: 'standard'
};
oCurrencyFormat = sap.ui.core.format.NumberFormat.getCurrencyInstance(oFormatOptions, oLocale);
oCurrencyFormat.format(1234.567, "USD"); // результат - USD1,234.57 (вместо символа валюты используется код валюты)oCurrencyFormat.format(1234.567, "JPY"); // результат JPY1,235 (вместо символа валюты используется код валюты)

Форматирования размера файла в SapUI5:

  • binaryFilesize: если значение установлено в true, то это значит, что 1 Kilobyte = 1024 Byte. Иначе 1 Kilobyte = 1000 Byte. По умолчанию установлена в false.

    Пример:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    var oFileSizeFormat =  sap.ui.core.format.FileSizeFormat.getInstance({
        binaryFilesize: true,
        decimals: 2
    });
     
    oFileSizeFormat.format(1023); //результат будет 1,023.00 Bytes 
    oFileSizeFormat = sap.ui.core.format.FileSizeFormat.getInstance({
        binaryFilesize: false,
        decimals: 2
    });
    oFileSizeFormat.format(1023); //результат будет 1.02 KB
  • FileSizeFormat:

    Пример:

    1
    2
    3
    4
    
    var oFileSizeFormat =  sap.ui.core.format.FileSizeFormat.getInstance();
     
    oFileSizeFormat.parse("1.23 MiB"); //результат 1289748.48
    oFileSizeFormat.parse("1 MB"); // результат 1230000

Подробней про формат размера файла — https://openui5.hana.ondemand.com/#/topic/24f340bdd59e4428aab30a20d14e2ebc.

Это все нативные средства форматирования, но в SapUI5 можно создать собственные методы для форматирования данных.

Пользовательское форматирование.

Вернемся к нашему предыдущему примеру, который мы делали в уроке 4.

Сделаем так, что при выводе числа у него отображалось две десятичные цифры.
Например, в модели число 12.1, но на экране будет отображено 12.10.

В контроллере определим форматтер:

/layout_sapui5/blob/master/webapp/controller/Main.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/m/MessageToast",
	"sap/ui/Device",
	"hello/layout/model/formatter",	"hello/layout/model/type/digits"
], function(Controller, MessageToast, Device, formatter, Digits) {	"use strict";
 
	return Controller.extend("hello.layout.controller.Main", {
 
		formatter: formatter, 
		onInit: function() {

определим число в JSON модели, которое будет в последствии выводить:

/layout_sapui5/blob/master/webapp/controller/Main.controller.js
1
2
3
4
5
6
var oData = {
	"name": "123456",
	"enabled": true,
	"date": new Date(),
	"price": "12.1"};

Сделаем сам форматтер, который мы указали — hello/layout/model/formatter и сделаем метод numberUnit, который мы после укажем в представлении:

/layout_sapui5/blob/master/webapp/model/formatter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
sap.ui.define([
	] , function () {
		"use strict";
		return {
			/**
			 * Rounds the number unit value to 2 digits
			 * @public
			 * @param {string} sValue the number string to be rounded
			 * @returns {string} sValue with 2 digits rounded
			 */
			numberUnit : function (sValue) {				if (!sValue) {
					return "";
				}
                                //принимаем пришедшее число sValue и задаем 2 цифры после запятой
				return parseFloat(sValue).toFixed(2);
			}
		};
	}
);

В представлении выводим число и указываем для него форматтер:

/layout_sapui5/blob/master/webapp/view/form.fragment.xml
1
2
3
4
<objectnumber number="{
              path: 'odata>/price',              formatter: '.formatter.numberUnit' }"></objectnumber>

Готово:
formatter

Так же собственные форматтеры используются и в примере из урока 8:

/DataBinding_sapui5/blob/master/webapp/view/Formatting.view.xml
1
2
3
4
5
6
<link href="{ parts: [ 'inputData/>/firstName', 'inputData>/lastName', 'inputData>/midName' ], formatter: '.formatMail' }" text="{i18n>sendEmail}"/>
 
…
 
<standardlistitem icon="{ path : 'globalData>typeId', formatter : 'alfa.DataBindingExample.model.formatter.formatIcon' }" type="Navigation" title="{globalData>type}" description="{globalData>name}"/>
</standardlistitem>

Принцип аналогичный, попробуйте разобраться сами.

Еще один примерчик из официальной документации — https://openui5.hana.ondemand.com/#/topic/0f8626ed7b7542ffaa44601828db20de.

Сортировка и фильтрация данных в JSON модели.

Создадим таблицу:

/DataBinding_sapui5/blob/master/webapp/view/SortingAndFiltering.view.xml
1
2
3
<table noDataText="Нет данных" id="table0" visible="{globalData>/showTable}"
items="{ path : '/Employees', sorter: { path: 'Pernr', descending: true } }">
…</table>

…и выведем в нее JSON модель:

/DataBinding_sapui5/blob/master/webapp/controller/SortingAndFiltering.controller.js
1
2
3
4
onInit: function() {
	var oModel = new sap.ui.model.json.JSONModel(); // создаем JSON модель
	oModel.loadData("./model/employees.json", "", false); //загружаем данные из /model/employees.json
	this.getView().byId("table0").setModel(oModel); // получаем таблицу с id = table0 и устанавливаем для нее модель

visible=»{globalData>/showTable}» — типичный пример property binding:

/DataBinding_sapui5/blob/master/webapp/view/SortingAndFiltering.view.xml
1
2
<checkbox text="Отобразить таблицу" selected="{globalData>/showTable}"/>
</checkbox>

Когда checkbox нажат selected=»{globalData>/showTable}»=true, следовательно visible=»{globalData>/showTable}»=true.

Property binding применяется и к полю поиска:

/DataBinding_sapui5/blob/master/webapp/view/SortingAndFiltering.view.xml
1
2
3
4
5
<flexbox width="100%" id="__box1">
	<items>
	<searchfield visible="{globalData>/showTable}" search="onTableSearch"/>	</searchfield></items>
</flexbox>

Поиск по элементам JSON модели.

Если введем какую-либо строку в SearchField и нажмем enter отработает метод search=»onTableSearch»:

/DataBinding_sapui5/blob/master/webapp/controller/SortingAndFiltering.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
onTableSearch: function(oEvt) {
	var aFilter = [], //создаем массив aFilter
	resFilter = []; //создаем массив resFilte
	var sQuery = oEvt.getParameter("query"); //получаем строку из поля поиска
	if (sQuery) { //если строка не пустая
		//добавляем в массив aFilter 3 элемента:
		//1) Поиск по полю LastName. Ищем строку, содержащую sQuery.
		//2) Поиск по полю FirstName. Ищем строку, содержащую sQuery.
		//3) Поиск по полю MidName. Ищем строку, содержащую sQuery.
		aFilter.push(new sap.ui.model.Filter("LastName", sap.ui.model.FilterOperator.Contains, sQuery));
		aFilter.push(new sap.ui.model.Filter("FirstName", sap.ui.model.FilterOperator.Contains, sQuery));
		aFilter.push(new sap.ui.model.Filter("MidName", sap.ui.model.FilterOperator.Contains, sQuery));
 
		//В массив resFilter добавляем массив aFilter, в котором содержаться условия поиска 
		//and: false - Вместо логического И будет использоваться логическое ИЛИ.
		//Другими словами, хотя бы одно поле из трех должно содержать строку поиска!
		resFilter.push(new sap.ui.model.Filter({
			filters: aFilter,
			and: false
		}));
	}
 
	var oList = this.getView().byId("table0"); //получаем таблицу
	var oBinding = oList.getBinding("items"); //биндинг таблицы
	oBinding.filter(resFilter); //применяем созданный фильтр
},

Поиск по элементам реализован!

Фильтрация в официальной документации — https://sapui5.hana.ondemand.com/#/topic/5295470d7eee46c1898ee46c1b9ad763.

Группировка и сортировка элементов JSON модели.

Сделаем сортировку и группировку таблицы по заданным параметрам.
Установку параметров будет делать в диалоговом окне, которое открывается по нажатию на кнопку:

/DataBinding_sapui5/blob/master/webapp/view/SortingAndFiltering.view.xml
1
2
<button icon="sap-icon://action-settings" press="onViewSettings">
</button>

По нажатию вызываем метод onViewSettings, в котором открываем диалог (диалоговые окна мы учились создавать в 7 уроке) и создаем список сортировки:

/DataBinding_sapui5/blob/master/webapp/controller/SortingAndFiltering.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
onViewSettings: function(oEvent) {
	if (!this._oDialog) {
                //создаем диалог из фрагмента
		this._oDialog = sap.ui.xmlfragment("alfa.DataBindingExample.view.TableViewSettingsDialog", this);
 
 
		var oCols = this.getView().byId("table0").getColumns(); // количество колонок
		var aCells = this.getView().byId("table0").getBindingInfo("items").template.getCells(); //получаем первую ячейку каждого столбца
 
//в созданный диалог добавляем еще элементы сортировки (SortItem) по количеству столбцов и с названиями, соответствующими названиям столбцов
		for (var i = 0; i < oCols.length; i++) {
			this._oDialog.addSortItem(new sap.m.ViewSettingsItem({
				text: oCols[i].getHeader().getBindingInfo("text").binding.oValue,
				key: aCells[i].getBindingInfo(i === 4 ? "value" : "text").parts[0].path,
				selected: i === 0
			}));
		}
	}
	this._oDialog.open();
,

Нажмем и вызовем диалог:
группировка и сортировка

Список элементов, по которым можно сортировать, мы только что динамически сделали в методе onViewSettings.

Список элементов для группировки мы указали в представлении:

/DataBinding_sapui5/blob/master/webapp/view/TableViewSettingsDialog.fragment.xml
1
2
3
4
5
6
<viewsettingsdialog id="SettingsId" confirm="handleViewSettingsConfirm">
	<groupitems>
		<viewsettingsitem text="Город" key="City"></viewsettingsitem>		<viewsettingsitem text="Орг единица" key="OrgehName"></viewsettingsitem>	</groupitems>
</viewsettingsdialog>

По нажатию на кнопку Ok применяем сортировку и группировку:

/DataBinding_sapui5/blob/master/webapp/controller/SortingAndFiltering.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
handleViewSettingsConfirm: function(oEvent) {
	var oView = this.getView(); //выбираем представление
	var oTable = oView.byId("table0"); //выбираем таблицу
 
	var mParams = oEvent.getParameters(); //параметры
	var oBinding = oTable.getBinding("items"); //биндинг
 
	var sPath;
	var bDescending;
	var vGroup;
	var aSorters = [];
 
	// группировка
	if (mParams.groupItem) {
		sPath = mParams.groupItem.getKey(); //получаем значение, по которому будет группировать
		bDescending = mParams.groupDescending; //по возрастающей или убывающей
		vGroup = this.mGroupFunctions[sPath];
		aSorters.push(new Sorter(sPath, bDescending, vGroup));
	}
 
	// сортировка
	sPath = mParams.sortItem.getKey(); //получаем значение, по которому будет группировать
	bDescending = mParams.sortDescending; //по возрастающей или убывающей
 
// для поля pernr особые условия сортировки. Так как надо сравнивать цифры из pernr, а не строки.
//Для этого создали функцию compareIntegers, которая описана ниже в данном контроллере
	if (sPath === "Pernr") {
		aSorters.push(new Sorter(sPath, bDescending, false, this.compareIntegers));
	} else {
		aSorters.push(new Sorter(sPath, bDescending));
	}
		oBinding.sort(aSorters);
	},

Отметим, что this.mGroupFunctions из группировки мы определили в методе инициализации onInit:

/DataBinding_sapui5/blob/master/webapp/controller/SortingAndFiltering.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
this.mGroupFunctions = {
	OrgehName: function(oContext) {
		var name = oContext.getProperty("OrgehName");
		return {
			key: name,
			text: name
		};
	},
 
	City: function(oContext) {
		var name = oContext.getProperty("City");
		return {
			key: name,
			text: name
		};
	}
};

Не забываем подключать необходимые библиотеки:

/DataBinding_sapui5/blob/master/webapp/controller/SortingAndFiltering.controller.js
1
2
3
4
5
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	'sap/ui/model/Filter',	'sap/ui/model/Sorter'], function(Controller, Filter, Sorter) {

Таким образом можно сортировать и группировать данные из JSON модели!

Про сортировку и группировку в официальной документации: https://sapui5.hana.ondemand.com/#/topic/5295470d7eee46c1898ee46c1b9ad763.html.