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

Пытаюсь написать модуль внутри которого можно будет работать с событиями.

define("CardModuleResponseInterceptor", ["terrasoft", "ext-base", "sandbox", "BaseModule"],
        function(Terrasoft, Ext, sandbox) {
                Ext.define("Terrasoft.configuration.CardModuleResponseInterceptor", {
                        alternateClassName: "Terrasoft.CardModuleResponseInterceptor",
                        extend: "Terrasoft.BaseModule",
                        sandbox: Ext.create(sandbox),
                        CardModuleResponseSUBSCRIBER: function(scope) {
                                this.sandbox.subscribe(
                                        "CardModuleResponse",
                                        function(args) {
                                                this.set("NewVar", args);
                                        },
                                        scope,
                                        [scope.sandbox.id + "_AddTenderSuccessAction"]
                                );
                        }
                });
                return Terrasoft.CardModuleResponseInterceptor;
        });

Так же в самом модуле, добавлена подписка на событие:
в схеме некоей карточки я добавляю модуль в зависимости, объявляю его экземпляр,
но когда дело доходит
define("LeadPageV2", ["UserUtilsMixin", "CardModuleResponseInterceptor"],
        function(UserUtilsMixin, CardModuleResponseInterceptor) {
...
        "onEntityInitialized": function() {
...
                //Объявляем экземпляр модуля-перехватчика события "CardModuleResponse"
                this.CardModuleResponseInterceptor = Ext.create("Terrasoft.CardModuleResponseInterceptor");
...

И в какой-то момент выполнения логики я вызываю
this.CardModuleResponseInterceptor.CardModuleResponseSUBSCRIBER(this);

Код внутри модуля исполняется успешно, во всех случаях кроме непосредственной подписки на события
В конечном итоге имеем ошибку
"Cannot read property 'messages' of null "
внутри bootstrap.js
...
getEventDescriptor: function(eventName) {
        var moduleDynamicMessages = this.getCurrentModuleDynamicMessages();
        if (moduleDynamicMessages[eventName]) {
                return moduleDynamicMessages[eventName];
        }
        var moduleDescriptor = core.getModuleDescriptor(this.moduleName);
        return (moduleDescriptor.messages) ? moduleDescriptor.messages[eventName] || null : null;
},
...

this.moduleName - оказывается в состоянии undefined

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

Нравится

12 комментариев

Делал модальное окно с общением между ним и карточкой из которой оно открывается через песочницу. Возможно будет полезно, вот здесь код и описание:
http://www.community.terrasoft.ru/forum/topic/17970#comment-63544
Т.к. модальное окно по сути тоже модуль и песочница там работала.

Ext.create(sandbox) - это что?

как создать модуль
https://academy.terrasoft.ru/documents/technic-sdk/7-10/dobavlenie-mini…

"Андросов Дмитрий" написал:Ext.create(sandbox) - это что?

Эксперимент после которого, собственно подписка уже двинулась дальше, изначального фейла в котором this.sandbox = undefined
Подглядел где-то в исходниках.
...
Переработал модуль, переосмыслив, почитав статью.

define("CardModuleResponseInterceptor", ["terrasoft", "ext-base", "sandbox", "BaseModule"],
	function(Terrasoft, Ext, sandbox) {
		Ext.define("Terrasoft.configuration.CardModuleResponseInterceptor", {
			alternateClassName: "Terrasoft.CardModuleResponseInterceptor",
			extend: "Terrasoft.BaseModule",
			Ext: null,
			sandbox: null,
			Terrasoft: null,
			viewModel: null,
			view: null,
			rootSope: {},
			init: function() {
				// Вызывает выполнение логики метода init() класса-родителя.
				this.callParent(arguments);
				this.sandbox.subscribe(
					"CardModuleResponse",
					function(args) {
						this.set("NewVar", args);
					},
					this.rootSope,
					[this.rootSope.sandbox.id + "_AddTenderSuccessAction"]
				);
			}
		});
		return Terrasoft.CardModuleResponseInterceptor;
	});

теперь собственно в карточке вызываю

Ext.create("Terrasoft.CardModuleResponseInterceptor", {rootSope: this});

но метод init не выполняется по какой-то причине.
Надо использовать метод loadModule ?

да, а вот создавать экземпляр вашего модуля на LeadPage не надо

"Андросов Дмитрий" написал:

да, а вот создавать экземпляр вашего модуля на LeadPage не надо


На правах, связанного вопроса...
Если я не могу/не надо создавать, как же я смогу передать контекст, при Ext.create(
я планировал передавать его - перегружая динамическое свойство, в объекте (2-ой аргумент конструктора)
Я так понимаю во время загрузки модуля, такой возможности уже не предоставляется
Или есть ?

PS: В двух словах, если можно, а в каких юзкейсах потребуется явное объявление экземпляра через Ext.create(?

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

this.CardModuleResponseInterceptor = Ext.create("Terrasoft.CardModuleResponseInterceptor", {rootScope: this});
this.sandbox.loadModule(this.CardModuleResponseInterceptor, {id: "someModuleId"});

?
Конкретно такой способ не работает к сожалению.
Еще попробовал так

this.sandbox.loadModule("CardModuleResponseInterceptor", {
	instanceConfig: {
		rootScope: this
	}
});

и так

this.sandbox.loadModule("CardModuleResponseInterceptor", {
        id: "CustomIdvalue"
	instanceConfig: {
		rootSope: this
	}
});

При загрузке модуля - ошибка " Cannot read property 'id' of undefined"
в core.js:581

По факту же отладка показывает что перегрузка "rootScope" не попадает в конструктор, через instanceConfig:

Ка-же все таки передать аргументы в конструктор ?

нет времени, только скриншоты


alternateClassName: "Terrasoft.CardModuleResponseInterceptor"

вот это имя в loadmodule и пишите

"Terrasoft.CardModuleResponseInterceptor" использовать невозможно.
Вызов кода модуля, и его метода init происходит через его имя "модуля" а не класса, Вы второпях ошиблись.
т.е.

define("CardModuleResponseInterceptor",  ...

Вызов модуля, происходит по

this.sandbox.loadModule("CardModuleResponseInterceptor");

Что же касается instanceConfig, его я нашел и попробовал сразу.

this.sandbox.loadModule("CardModuleResponseInterceptor", {
	instanceConfig: {
		rootScope: this
	}
});

Но по неизвестной причине - мне не удается получить значения в контексте init метода.
При этом инициируя через Ext.create и явный вызов init метода у экземпляра
как раз аргументы конструктора передаются корректно, но зато не функционирует sandbox
С этого собственно все и началось.

Не до конца ясен комментарий к parameters и instanceConfig

Used only for instantiated modules

Как это понять "инстанцированных модулях" ?
Какие модули "инстанцированные" а какие нет ?
Как сделать свой модуль соответвующим ?

function loadModule(moduleName, config) {
	if (!config) {
		config = {};
	}
	if (!config.id) {
		config.id = moduleName;
	}
	performanceCounterManager.start(config.id + "_loadModule");
	config.moduleName = moduleName;
	var module = getModuleDescriptor(moduleName);
	var cssDeps = module.css ? bootstrap.mapResourcesToPath(module.css, module.path, "css") : [];
	var lessDeps = module.less ? bootstrap.mapResourcesToPath(module.less, module.path, "less") : [];
	createContext(moduleName, config);
	require(["ext-base", moduleName].concat(cssDeps).concat(lessDeps), function(Ext, exportedModule) {
		if (typeof exportedModule === "function") {
// инстанцируемый модуль, это модуль, функция-фабрика которого возвращает функцию (Ext-класс), у вас как раз такой
//https://academy.terrasoft.ru/documents/technic-sdk/7-10/koncepciya-amd-ponyatie-modulya
			createModuleInstance(exportedModule, moduleName, config);
		} else {
			processModule(exportedModule, config);
			exportedModule.isDestroyed = false;
			exportedModule.instanceId = Terrasoft.generateGUID();
			loadedModules[config.id] = exportedModule;
		}
	});
	return config.id;
}
function createModuleInstance(modulesFactory, moduleName, config) {
	var moduleId = config.id;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//чтобы модуль проинстанцировался нужно, чтобы не существовало инстанса с таким ИД
	if (!requirejs.defined(moduleId)) {
		var factoryName = moduleName + "_factory";
		if (!(factoryName in contexts)) {
			contexts[factoryName] = contexts[moduleId];
		}
		delete contexts[moduleId];
		requirejs.undef("sandbox_" + moduleId);
		requirejs.undef("ext_" + moduleId);
		requirejs.undef("terrasoft_" + moduleId);
		createContext(moduleId, config);
		define(moduleId, ["ext-base", "terrasoft", "sandbox"], function(Ext, Terrasoft, sandbox) {
			var context = {};
			var instanceConfig = config.instanceConfig;
			if (instanceConfig && (typeof instanceConfig === "object")) {
				context = prepareParameters(instanceConfig);
			}
			if (config.parameters && (typeof config.parameters === "object")) {
				context.parameters = prepareParameters(config.parameters);
			}
			context.Ext = Ext;
			context.sandbox = sandbox;
			context.Terrasoft = Terrasoft;
			var Constructor;
			var moduleInstance;
			if (modulesFactory.$isClass === true) {
				Constructor = modulesFactory;
				moduleInstance = new Constructor(context);
			} else {
				Constructor = safeExecute({
					fn: modulesFactory,
					scope: modulesFactory,
					args: [context],
					errorInfo: {
						moduleName: moduleName,
						contexts: contexts,
						chain: chain,
						moduleId: moduleId
					}
				});
				moduleInstance = new Constructor();
			}
			moduleInstance.isDestroyed = false;
			loadedModules[moduleId] = moduleInstance;
			return moduleInstance;
		});
	}
	require([moduleId], function(module) {
		processModule(module, config);
	});
}

в результате проследите, чтобы ИД модуля был уникален и делайте destroy модуля, когда он больше не нужен

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