SapUI5: Как поменять стандартный файл/метод

SapUI5 позволяет решать ряд типичных задач. Но как только возникают какие-то не стандартные потребности, приходиться переходить на JS в связке с JQuery. В таких задачах зачастую необходимо отредактировать стандартный элемент управления, метод, библиотеку.
В этом посте посмотрим как можно переписать стандартный файл или переопределить стандартный метод.

Пример, который мы будем рассматривать ниже, можно импортировать в свой WebIDE отсюда https://github.com/kannade/sapui5_redefine.

В примере на экран выведем 4 кнопки:

  • Кнопка №1 — самая обычная кнопка sap.m.Button;
  • Кнопка №2 — полностью скопируем стандартный элемент в пользовательский и выведем на экран;
  • Кнопка №3 — это та же самая кнопка №2, но выведем ее через JS;
  • Кнопка №4 — унаследованная стандартная кнопка с измененным методом;

redefine button

Кнопка №1. Выведем sap.m.Button

Просто нарисуем кнопку:

/sapui5_redefine/blob/master/webapp/view/Main.view.xml
< Button text="text button 1" />

Кнопка №2. Редактируем стандартный элемент управления и выводим в XML.

Итак, мы хотим отредактировать стандартный код элемента управления «Кнопка» (sap.m.Button).
Для этого нам нужно получить исходные коды кнопки (sap/m/Button.js) и скрипта, который эту кнопку рисует (sap/m/ButtonRenderer.js). Скачать их можно либо с официальной страницы OpenUI5 на GitHub — https://github.com/SAP/openui5, либо вытянуть из того ядра, которое подгружается в вашем приложении.

На гитхабе Button.js можно скачать тут https://github.com/SAP/openui5/blob/master/src/sap.m/src/sap/m/Button.js, но проблемы могут возникнуть, если ваша версия SapUI5 отличается от той, которая на гитхабе.

Для копирования исходных файлов из ядра переходим в инструменты разработчика Google Chrome (F12) на вкладку Source, в левой части экрана ищем sapui5.hana.ondemand.com -> resources -> sap -> m -> Button-dbg.js:

path button

Если файл называется Button.js (минифицированный код (удалены пробелы, отступы, переименованы переменные)), а не Button-dbg.js (код для дебага (читаемый код)), попробуйте добавить url параметр sap-ui-debug=true и обновить страницу.

Убираем из названия файлов «-dbg» и копируем их в наш проект в папку controls:
my button

Перейдем в файл Button.js и заменим:

/openui5/blob/master/src/sap.m/src/sap/m/Button.js
var Button = Control.extend("sap.m.Button",

на

/sapui5_redefine/blob/master/webapp/controls/Button.js
var Button = Control.extend("nickcode_ru_redefine.controls.Button",

где nickcode_ru_redefine — наш NameSpace, .controls.Button — путь до файла Button.js.

и поменяем путь загрузки для файла library, так как в исходном варианте sapui5 будет искать данный файл в текущей папке:

/openui5/blob/master/src/sap.m/src/sap/m/Button.js
sap.ui.define([
	'jquery.sap.global',
	'./library',	'sap/ui/core/Control',

на

/sapui5_redefine/blob/master/webapp/controls/Button.js
sap.ui.define([
	'jquery.sap.global',
	'sap/m/library',	'sap/ui/core/Control',

Так, теперь отредактируем какой-нибудь метод скопированного элемента управления «Кнопка». Давайте сделаем так, чтобы в момент рисования кнопки, к тексту, который пишется на кнопке, добавлялась какая-либо строка.
Для этого перейдем в sap/m/ButtonRenderer.js и отредактируем тот момент, где для кнопки устанавливается текст:

/sapui5_redefine/blob/master/webapp/controls/ButtonRenderer.js
// write button text
if (sText) {
	oRm.write("<span ");
	oRm.addClass("sapMBtnContent");
	// check if textDirection property is not set to default "Inherit" and add "dir" attribute
	if (sTextDir !== TextDirection.Inherit) {
		oRm.writeAttribute("dir", sTextDir.toLowerCase());
	}
	oRm.writeClasses();
	oRm.writeAttribute("id", oButton.getId() + "-content");
	oRm.write(">");
 
	if (bRenderBDI) {
		oRm.write("<bdi>");
	}
 
	//ПРИБАВИМ К ТЕКСТУ СТРОКУ "_123"	//oRm.writeEscaped(sText);	oRm.writeEscaped(sText + "_123"); 
	if (bRenderBDI) {
		oRm.write("</bdi>");
	}
	oRm.write("</span>");
}

Перейдем к представлению и выведем нашу новую кнопку!

/sapui5_redefine/blob/master/webapp/view/Main.view.xml
<mvc:view controllerName="nickcode_ru_redefine.controller.Main" xmlns:html="http://www.w3.org/1999/xhtml"
	xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:myself="nickcode_ru_redefine.controls">	<app id="idAppControl">
		<pages>
			<page title="{i18n>title}" id="idPage">
				<content>
					<button text="text button 1"></button>
					<myself:button text="text button 2"></myself:button>				</content>
			</page>
		</pages>
	</app>
</mvc:view>

Обратите внимание, что мы определяем новый NameSpace (указываем путь до папки с button.js): xmlns:myself=»nickcode_ru_redefine.controls», а затем рисуем кнопку, используя наш скопированный элемент: <myself:Button text=»text button 2″ />

Кнопка №3. Редактируем стандартный элемент управления и выводим в JS.

Нарисуем кнопку №2, но только в JS:

/sapui5_redefine/blob/master/webapp/controller/Main.controller.js
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"nickcode_ru_redefine/controls/Button" //путь до скопированной кнопки], function(Controller, Button) {
	"use strict";
 
	return Controller.extend("nickcode_ru_redefine.controller.Main", {
 
		onInit: function() {
			var oButton = new Button({ //создаем кнопку				text: "button_from_js"
			});
 
			this.getView().byId("idPage").addContent(oButton); //добавляем кнопку на экран
		}
 
	});
});

Таким образом можно редактировать практически любые стандартные файлы SapUI5, но только стоит помнить о зависимостях и ссылках на другие стандартные файлы (как это было чуть выше с library).

Кнопка №4. Наследуем стандартный элемент управления и редактируем метод.

Перейдем к 4 кнопки!
Представим, что нам надо отредактировать какой-то один метод элемента управления. В таком случае копировать все файлы к себе в проект не имеет смысла, давайте переопределим только 1 метод!

Создадим файл Button3, в котором расширим стандартный элемент управления sap.m.Button и перепишим стандартный метод setText этого элемента:

/sapui5_redefine/blob/master/webapp/controller/Main.controller.js
sap.ui.define([
	'sap/m/ButtonRenderer' //файл отрисовщик для кнопки
], function(
	ButtonRenderer
) {
	"use strict";
 
	//Расширяем стандартный sap.m.Button
	var Button = sap.m.Button.extend("nickcode_ru_redefine.controls.Button3", {		renderer: ButtonRenderer //указываем стандартный скрипт отрисовки элемента	}); 
	//Переписываем стандартный метод setText
		Button.prototype.setText = function(sText) {
		var sValue = this.getText();
 
		if (sText === null || sText === undefined) {
			sText = "";
		}
 
		if (sValue !== sText) {
			var oDomRef = this.getDomRef("content");
			var bShouldSupressRendering = !!oDomRef;
 
			// Render control if element is not available in the DOM
			//При вызове метода setText добавим с тексту кнопки строку "_123"
			//this.setProperty("text", sText, bShouldSupressRendering);
			this.setProperty("text", sText + "_123", bShouldSupressRendering);
 
			if (bShouldSupressRendering) {
				// Get text to have the type conversation for non-string values done by the framework
				sText = this.getText();
				oDomRef.innerHTML = jQuery.sap.encodeHTML(sText);
				this.$("inner").toggleClass("sapMBtnText", !!sText);
			}
		}
 
		return this;
	};
 
 
	return Button;
 
});

Попробуем нарисовать кнопку №4 и вызвать переписанный метод setText:

/sapui5_redefine/blob/master/webapp/controller/Main.controller.js
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"nickcode_ru_redefine/controls/Button",
	"nickcode_ru_redefine/controls/Button3" //указали путь до унаследованной кнопки], function(Controller, Button, Button3) {
	"use strict";
 
	return Controller.extend("nickcode_ru_redefine.controller.Main", {
 
		onInit: function() {
			var oButton = new Button({
				text: "button_from_js"
			});
 
			this.getView().byId("idPage").addContent(oButton);
 
			//создаем унаследованную кнопку
			var oButton3 = new Button3({				text: ""
			});
 
			this.getView().byId("idPage").addContent(oButton3);
			//Вызываем переписанный метод setText
			oButton3.setText("button_from_js3");		}
 
	});
});

Таким образом можно как угодно изменять стандартные элементы управления, стандартную логику SapUI5, визуализацию элементов, да и все, что в голову придет… даже создавать свои комплексные элементы управления, но это тема уже для другого поста ;).