SapUI5: Передача объекта, текста из одного контроллера в другой в рамках одного приложения

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

Пример приложения, которое используется в данном посте — https://github.com/kannade/sapui5_transfer_data/.

Передаем данные используя модель

Самый логичный и удобный способ передачи данных между контроллерами — модель!

Как создавать модель, заполнять ее и читать мы уже учились тут https://nickcode.ru/sapui5/sapui5-igraem-s-modelyu.html.

Пройдемся кратко по основным моментам.

В модель мы можем записать как обычный текст:

/sapui5_transfer_data/blob/master/webapp/Component.js
//Получаем текущий, предыдущий и следующий год
var d = new Date();
var currentYear = parseInt(d.getFullYear(), 10);
var prevYear = parseInt(d.getFullYear() - 1, 10);
var nextYear = parseInt(d.getFullYear() + 1, 10);
 
//Первый вариант записи - setProperty
var testModel = this.getModel("testmodel");
testModel.setProperty("/items/0/key", prevYear.toString());
testModel.setProperty("/items/1/key", currentYear.toString());
testModel.setProperty("/items/2/key", nextYear.toString());
 
//Второй вариант записи
var aData = testModel.getData();
for (var i = 0; i < aData.items.length; i++) {
	aData.items[i].load = true;
}
 
testModel.refresh();

затем вывести его:

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
var oComp = this.getOwnerComponent(); //компонент, на который забиндина наша модель
var testModel = oComp.getModel("testmodel"); // получили модель
var aData = testModel.getData(); //массив данных модели
 
//достанем текст из модели и поместим его в Label
this.getView().byId("oneLabel").setText(aData.items[0].key);

так и можем передать объект:

/sapui5_transfer_data/blob/master/webapp/Component.js
//Установим объект через модель
var oLabel2 = new sap.m.Label({
	text: "Label from Model from Component"
});
 
testModel.setProperty("/desc", oLabel2);

и вывести его:

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
//достанем объект из модели
var verticalL = this.getView().byId("verL");
var oLabel2 = testModel.getProperty("/desc");
verticalL.addContent(oLabel2);

Передаем данные используя третий файл

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

В качестве такого файла будем использовать Utils.js:

/sapui5_transfer_data/blob/master/webapp/model/Utils.js
sap.ui.define([], function() {
	"use strict";
 
	var _objPernr = null;
 
	return {
 
		//сохраняем табельный номер
		setPernr: function(objPernr) {
			_objPernr = objPernr;
		},
 
		//возвращаем ранее сохраненный табельный номер
		getPernr: function() {
			return _objPernr;
		}
 
	};
});

Посмотрим как это работает!
Прежде всего не забываем подключить Utils.js там, где мы хотим его использовать:

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"transfer/info/model/Utils",], function(Controller, Utils) {	"use strict";

Сохраняем текст:

/sapui5_transfer_data/blob/master/webapp/Component.js
//Установим текст через Utils
Utils.setPernr("00001234");

Отдаем текст:

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
//достанем текст из utill.js
this.getView().byId("threeLabel").setText(Utils.getPernr());

Сохраняем объект:

/sapui5_transfer_data/blob/master/webapp/Component.js
//Установим объект через Utils
var oLabel = new sap.m.Label({
	text: "Label from Component"
});
Utils.setOLabel(oLabel);
 
//Установим объект через Utils
var oInput = new sap.m.Input({
	value: "Input from Component"
});
Utils.setOInput(oInput);

Отдаем объект:

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
//достанем объекты из utill.js
var oSimpleForm = this.getView().byId("SimpleFormChange354");
var oInput = Utils.getOInput();
var oLabel = Utils.getOLabel();
oSimpleForm.addContent(oLabel);
oSimpleForm.addContent(oInput);

Передаем данные используя глобальный объект

Третий вариант не рекомендуется к использованию, но тоже имеет право на жизнь.

Сохраняем текст и объект:

/sapui5_transfer_data/blob/master/webapp/Component.js
//установим текст и объект глобально
var oLabel3 = new sap.m.Label({
	text: "Global Label from Component"
});
 
jQuery.sap.getObject("sap.alfa.dataBinding", 0);
sap.alfa.dataBinding = {
	key1: "Тест текст из глобального объекта",
	key2: oLabel3
};

Отдаем текст и объект:

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
//достанем текст из глобального объекта
this.getView().byId("twoLabel").setText(sap.alfa.dataBinding.key1);
 
//Достанем объект из глобального объекта
verticalL.addContent(sap.alfa.dataBinding.key2);

Передача события между двумя контроллерами / компонентами (EventBus).

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

<core:componentcontainer height="100%" id="list" propagateModel="true" name="component.Tree" usage="treeF4"
				settings="{ oDataModel : 'oTreePeopleModel' }" async="true" class="treeContainer"></core:componentcontainer>

в manifest.json :

"sap.ui5": {
…
"componentUsages": {
	"treeF4": {
		"name": "component.Tree",
		"settings": {
			"url": "/sap/bc/opu/odata"
		},
		"componentData": "{ hhelo }"
	}
}
 
}

Надо связать два компонента.
Например, когда происходит какое-то событие в component.Tree, передавать его в основное приложение.

Поможет нам EventBus!

Вернемся к нашему примеру и посмотрим как использовать EventBus в SapUI5 и передать информацию или объект из одного приложения / контроллера в другой!

Передадим событие с переменной d, в которую чуть выше мы записали объект с текущей датой (var d = new Date();)

/sapui5_transfer_data/blob/master/webapp/Component.js
//Передадим событие в другой контроллер
var oEventBus = sap.ui.getCore().getEventBus();
 
oEventBus.publish(
	"way1", "afterInitComp", d
);

, где way1 — канал, afterInitComp — название события, d — передаваемый объект.

перейдем в другой контроллер и подпишимся на событие

/sapui5_transfer_data/blob/master/webapp/controller/Main.controller.js
onInit: function () {
	// подписываемся на событие
	var oEventBus = sap.ui.getCore().getEventBus();
 
	oEventBus.subscribe(
		"way1", //канал
		"afterInitComp", //название события
		this.onAfterInitComp, //вызываем метод onAfterInitComp в данном (this) контроллере
		this
	);
},
 
//объявили метод, который будет вызываться, при отправке события из компонента
onAfterInitComp: function (channel, event, item) {
	MessageToast.show(item);
}

Вот и все! При загрузке приложения oEventBus.publish будет отправлять событие, а из другого компонента можно подписаться oEventBus.subscribe на это событие и вызывать какой-либо метод.

Чуть поподробней про EventBus можно почитать тут — https://blogs.sap.com/2015/10/25/openui5-sapui5-communication-between-controllers-using-publish-and-subscribe-from-eventbus/ и тут https://stackoverflow.com/questions/25382988/how-to-use-geteventbus-method-in-sapui5.

Такие дела :).