Технические вопросы
7.x

Пользовательский модуль с работоспособным 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
Подглядел где-то в исходниках.
...
Переработал модуль, переосмыслив, почитав статью.
[javascript]
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;
});
[/javascript]
теперь собственно в карточке вызываю
[javascript]
Ext.create("Terrasoft.CardModuleResponseInterceptor", {rootSope: this});
[/javascript]
но метод init не выполняется по какой-то причине.
Надо использовать метод loadModule ?

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

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

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


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

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

а может я могу как-то загрузить, конкретный созданный экземпляр, вот как-то так
[javascript]
this.CardModuleResponseInterceptor = Ext.create("Terrasoft.CardModuleResponseInterceptor", {rootScope: this});
this.sandbox.loadModule(this.CardModuleResponseInterceptor, {id: "someModuleId"});
[/javascript]
?
Конкретно такой способ не работает к сожалению.
Еще попробовал так
[javascript]
this.sandbox.loadModule("CardModuleResponseInterceptor", {
instanceConfig: {
rootScope: this
}
});
[/javascript]
и так
[javascript]
this.sandbox.loadModule("CardModuleResponseInterceptor", {
id: "CustomIdvalue"
instanceConfig: {
rootSope: this
}
});
[/javascript]

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

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

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

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


alternateClassName: "Terrasoft.CardModuleResponseInterceptor"

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

"Terrasoft.CardModuleResponseInterceptor" использовать невозможно.
Вызов кода модуля, и его метода init происходит через его имя "модуля" а не класса, Вы второпях ошиблись.
т.е.
[javascript]
define("CardModuleResponseInterceptor", ...
[/javascript]
Вызов модуля, происходит по
[javascript]
this.sandbox.loadModule("CardModuleResponseInterceptor");
[/javascript]

Что же касается instanceConfig, его я нашел и попробовал сразу.
[javascript]
this.sandbox.loadModule("CardModuleResponseInterceptor", {
instanceConfig: {
rootScope: this
}
});
[/javascript]
Но по неизвестной причине - мне не удается получить значения в контексте init метода.
При этом инициируя через Ext.create и явный вызов init метода у экземпляра
как раз аргументы конструктора передаются корректно, но зато не функционирует sandbox
С этого собственно все и началось.

Не до конца ясен комментарий к parameters и instanceConfig
[javascript]
Used only for instantiated modules
[/javascript]
Как это понять "инстанцированных модулях" ?
Какие модули "инстанцированные" а какие нет ?
Как сделать свой модуль соответвующим ?

[javascript]
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-…
createModuleInstance(exportedModule, moduleName, config);
} else {
processModule(exportedModule, config);
exportedModule.isDestroyed = false;
exportedModule.instanceId = Terrasoft.generateGUID();
loadedModules[config.id] = exportedModule;
}
});
return config.id;
}
[/javascript]

[javascript]
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);
});
}
[/javascript]

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

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