Урок 5. SapUI5: Собственные типы данных. Property binding.

Продолжим работать над предыдущим проектом (https://github.com/kannade/layout_sapui5/).

В sapui5 есть встроенные типы данных, например sap.ui.model.type.String, которому мы ограничили длину до 5 символов:

/layout_sapui5/blob/master/webapp/view/form.fragment.xml
1
<input id="first" value="{ path: 'odata/>/enabled', type: 'sap.ui.model.type.String', constraints: {minLength : 1, maxLength : 5} }">

но, sapui5 предоставляет возможность сделать пользовательские типы, чем мы сейчас и займемся.

Сделаем тип, который будет содержать в себе 6 цифр. После каждых 2-х цифр должен следовать символ «-«.

Создадим файл {пространство имен}/model/type/digits.js:

/layout_sapui5/blob/master/webapp/model/type/digits.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
sap.ui.define(["sap/ui/model/SimpleType", "sap/ui/model/ValidateException"],
	function(SimpleType, ValidateException) {
 
		return SimpleType.extend("hello.layout.model.type.digits", {
 
formatValue: function(sValue, sInternalType) {	//добавим "-" после каждых двух цифр
	var aDigits = sValue.split("");
	var sOutput = "";
 
	$.each(aDigits, function(i, iDigit) {
		if ((i > 0) && (i % 2 === 0)) {
			sOutput = sOutput + "-" + iDigit;
		} else {
			sOutput += iDigit;
		}
		});
		return sOutput;
		},
 
parseValue: function(sValue) {	return sValue.replace(/-/g, "");
},
 
validateValue: function(sValue) {	var aDigits = sValue.split("");
	if (aDigits.length !== 6) {
		throw new ValidateException(sValue + " не корректный номер телефона");
	}
}
});
 
});
  • formatValue — метод для форматирования значение на экране пользователя. Например, если после каждых двух цифр нам надо ставить тире, то эта логика настраивается в formatValue.
  • parseValue — метод для внутреннего представления. Допустим ввели номер телефона «34-14-24», но в JS мы должны представить эту строку как «341424».
  • validateValue — метод валидации.

parseValue вызывается при вводе любого символа в поле ввода, затем отрабатывает validateValue и если ошибки отсутствуют сработает formatValue.

Загрузим только что созданный тип в контроллере:

/layout_sapui5/blob/master/webapp/controller/Main.controller.js
1
2
3
4
5
6
7
8
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";

Применим его для поля ввода в XML представлении:

/layout_sapui5/blob/master/webapp/view/form.fragment.xml
1
2
3
4
5
6
7
8
9
10
11
<input enabled="{odata/>/enabled}" value="{ path: 'odata>/name', type: 'hello.layout.model.type.digits' }" valueLiveUpdate="true"><layoutdata>
	<l:griddata span="L4 M6 S6"></l:griddata>
</layoutdata>
 
 
<text text="{odata>/name}">
	<layoutdata>
		<l:griddata span="L4 M6 S6"></l:griddata>
	</layoutdata>
</text>

Что мы сделали этим кодом:

  • Присвоили первому Input пользовательский тип hello.layout.model.type.digits.
  • Прописали свойство valueLiveUpdate=»true», благодаря которому в Text значения будут меняться при любом изменении значения в Input.
  • Забиндили значение из Input на модель «odata» (которую мы описали в 4 уроке): path: ‘odata>/name’.
  • В Text реализовали Property Binding. Присвоили свойству text значение text=»{odata>/name}».

При любом изменении поля Input, значения в Text также будут меняться!

Плюс, если значение из поля не будет соответствовать маске xx-xx-xx (где x — цифра), мы получим ошибку:
custom type sapui5

Как отслеживать ошибки в SapUI5?

Хорошо, а теперь давайте сделаем так, чтобы при нажатии на кнопку происходила проверка поля. Если есть ошибка — выводилась ошибка, если все хорошо — выводилось значение поля.

В методе onInit контроллера включаем отслеживание ошибок:

/layout_sapui5/blob/master/webapp/controller/Main.controller.js
1
2
// Register the view with the message manager
sap.ui.getCore().getMessageManager().registerObject(this.getView(), true);

На кнопку повесим событие onPressSubmit:

/layout_sapui5/blob/master/webapp/view/form.fragment.xml
1
2
<button text="Submit" icon="sap-icon://paper-plane" press="onPressSubmit">
</button>

Опишем событие в onPressSubmit контроллере:

/layout_sapui5/blob/master/webapp/controller/Main.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
onPressSubmit: function() {
	var arr = sap.ui.getCore().getMessageManager().getMessageModel().oData;
 
	for (var i = 0; i < arr.length; i++) {
		if (arr[i].code == undefined &&	arr[i].type == sap.ui.core.MessageType.Error) {
			var sTarget = arr[i].getTarget();
			var oElem = sap.ui.getCore().byId(sTarget.substr(0, sTarget.indexOf("/")));
			if (oElem) {
				oElem.focus();
			}
			MessageToast.show(arr[i].message);
			return true;
		}
	}
 
		MessageToast.show(this.getView().byId("idFormFrag--first").getValue() +
		" " +
		this.getView().getModel("odata").getData().name +
		sap.ui.getCore().byId("__xmlview0--idFormFrag--second").getValue()
		);
}

Итак, что тут у нас происходит…
Мы объявляем массив arr, в каждом элементе которого у нас содержится ошибка.
Далее перебираем все ошибки (элементы массива) с определенным кодом (undefined) и типом (sap.ui.core.MessageType.Error). Переводим фокус на элемент с ошибкой (oElem.focus()) и выводим сообщение с текстом ошибки.

Если массив ошибок пустой, то выводим сообщение:

  • Получаем значение из первого поля (в примере поле Num 1, с ограничением по количеству символов (до 5)) — this.getView().byId(«idFormFrag—first»).getValue()
  • + значение из модели (наши 4 цифры) — this.getView().getModel(«odata»).getData().name
  • + значение из третьего поля — sap.ui.getCore().byId(«__xmlview0—idFormFrag—second»).getValue()

Каждое из трех значений мы получили разными способами:

  • this.getView().byId(«idFormFrag—first»).getValue() — получили значение, обратившись к элементу через его представление.
  • this.getView().getModel(«odata»).getData().name — получаем значение из модели (ЛУЧШИЙ ВЫБОР).
  • sap.ui.getCore().byId(«__xmlview0—idFormFrag—second»).getValue() — получили значение, обратившись к элементу напрямую по id.