Проблема с контролом и onEntityInitialized

Всем доброго времени суток.

Версия 7.10.

Ситуация такая: сделал свой контрол в соответствии с инструкцией из комментариев отсюда: https://community.terrasoft.ru/forum/topic/25285#comment-67717

Контрол похож на то, что описано там, разница в том, что добавляет не div, а элемент canvas с определённым id в DOM на страницу контакта. Пробуем для решения определённой задачи (образец подписи клиента, получается через canvas и сохраняется в отдельную колонку в формате base64).

Далее в onEntityInitialized ContactPageV2 делаю следующее:

onEntityInitialized: function() {
                                this.callParent(arguments);                    
                                var canvas = document.getElementById("UsrTestUsrSignControl-usr-my-control");
                        var context = canvas.getContext("2d");

//Дальнейшие действия
},

UsrTestUsrSignControl-usr-my-control - id элемента canvas.

Обнаружил, что в некоторых случаях на стадии getContext вываливается ошибка - скрипт не находит элемента по id. При это именно взятие по id необходимо для работы с канвасом, а работа внутри ContactPageV2 - чтобы сохранить результат в колонку контакта.

Вопрос - можно ли как-нибудь отследить загрузку контрола на страницу? Может быть, внутри самого контрола? Попробовал добавить document.getElementById внутрь init - то же самое.

Нравится

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

Обнаружил, что элемент доступен внутри события initDomEvents

Соответственно, вопрос меняется на "как передать данные в ContactPage".

Может быть, через sandbox?

Загрузка всех элементов на страницу "asynchronous as fuck", как говорится. В onEntityInitialized доступна модель страницы, но не факт, что элементы погрузились. Можно попробовать вставить функцию, реагирующую на рендер контрола:

"values": {
	....
	"afterrender": {bindTo: "onControlRendered"}
}

Данила, а точно есть такое - afterrender? Может быть onRender?

Попробовал - вообще функция не вызывается. Добавляю в values при подключении контрола.

Здравствуйте,
Можете подписатся в init-е на событие добавления в dom вашего элемента, подробнее:
https://toster.ru/q/18926
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_even…

"Смородинов Денис" написал:Данила, а точно есть такое - afterrender?

У Terrasoft.Label есть. Вообще должно событие быть, если контрол наследуется от Terrasoft.Component.
Судя по NUI Docs

{
		"operation": "insert",
		"name": "UsrTest",
		"values": {
			"layout": {
				"colSpan": 12,
				"rowSpan": 1,
				"column": 0,
				"row": 0,
				"layoutName": "GeneralInfoTabGridLayout97349c91",
			},
			"onAfterRender": {
				"bindTo": "onCanvasRendered"
			},
			"generator": "UsrSignControlGenerator.generateUsrSignControl",
			"visible": true
		},
		"parentName": "GeneralInfoTabGridLayout97349c91",
		"propertyName": "items",
		"index": 0
	},

И в методах:

onCanvasRendered: function(){
				console.log("rendered");
				var canvas = document.getElementById("UsrTestUsrSignControl-usr-my-control");
				console.log(canvas);
			},

Так не работает, даже просто "rendered" не выводит. afterrender вместо onAfterRender - тоже.

Контрол сам точно по той схеме, т.е. наследуется от компонента.

"Смородинов Денис" написал:Соответственно, вопрос меняется на "как передать данные в ContactPage".

Может быть, через sandbox?

Возможно, этот путь будет проще?

"Смородинов Денис" написал:Возможно, этот путь будет проще?

Думаю нет)

Получилось вот так (подправил генератор из вашей ссылки в посте):

generateTmMyControl: function(config) {
	debugger;
        var TmMyControl = {
                className: "Terrasoft.TmMyControl",
                id: config.name + "TmMyControl",
                selectors: {wrapEl: "#" + config.name + "TmMyControl"},
                layout: config.layout || {},
                afterrender: {bindTo: config.onAfterRender}, //добавил чисто на всякий случай
                afterrerender: {bindTo: config.onAfterRender} //контрол почему-то ререндерится, у меня на тестовой системе срабатывает именно это событие
        };
        if (!Ext.isEmpty(config.wrapClassName)) {
                TmMyControl.classes = {
                        wrapClassName: config.wrapClassName
                };
        }
        return TmMyControl;
},

Данила, спасибо, работает!

То есть получается, методы нужно добавлять в генератор.

"Варфоломеев Данила" написал:

Получилось вот так (подправил генератор из вашей ссылки в посте)

Привет. Есть ли идеи вот насчет чего?:

{
	"operation": "insert",
	"name": "Containment",
	"values": {
		"itemType": 2,
		"markerValue": "added-detail",
		"afterrender": {
			"bindTo": "getEnableDetails"
		},
		"afterrerender": {
			"bindTo": "getEnableDetails"
		}
	},
	"parentName": "QuickAnalysisTabContainer",
	"propertyName": "items",
	"index": 6
}

Соответственно, сам метод, который вешается на послерендер допустим что-то выводит в консоль.
На детали очень странное поведение.

Как только открываю табу, на которой должна быть деталь - моментально идет вызов метода и вывод в консоль. При этом сама деталь не грузится и запросы никакие никуда не идут на получение детали и её данных. Это оочень странно. И в DOM-е ни одного упоминания об этой детали. Т.е. грубо говоря вообще никакого рендера не произошло. Деталь не появляется на карточке. Никак.

ЧЯДНТ?

"Темченко Кирилл Александрович" написал:Деталь не появляется на карточке.

Смотрим стандартный генератор детали:

generateDetail: function(config) {
	var detailContainerId = this.getControlId(config, "Terrasoft.Container");
	var result = this.getDefaultContainerConfig(detailContainerId, config);
	result.tag = {
		detailName: config.name,
		containerId: detailContainerId
	};
	result.markerValue = config.name + "DetailContainer";
	result.afterrender = {
		bindTo: this.defaultLoadDetailMethodName
	};
	result.afterrerender = {
		bindTo: this.defaultLoadDetailMethodName
	};
	Ext.apply(result, this.getConfigWithoutServiceProperties(config, []));
	this.applyControlConfig(result, config);
	return result;
},

Видно, что на afterrender и afterrerender вешается метод loadDetail. (this.defaultLoadDetailMethodName = "loadDetail"). Далее ваши конфиг из диффа перетирает рендеры - this.applyControlConfig(result, config)

В итоге. Как задумывалось: рендерится контейнер, после рендера в него грузится грид детали (уж не знаю что там в методе loadDetail)
Как происходит: рендерится контейнер, вызываются ваши методы. деталь соответственно не загружается.

п.с. это всё в теории, времи тестить совсем нет)

"Варфоломеев Данила" написал:

п.с. это всё в теории, времи тестить совсем нет)

я на то и подумал. семантически это, конечно, не комильфо. на то оно и after. и когда я привязываю свои методы, по идее не должен задумываться, что уже висит что-то ванильное, которое я затру. ну да и ладно. задачу решил по-своему. через DOM события.

спасибо за помощь.

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