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

Был ли у кого-то опыт размещения данного раздела на карточке? 

 

Нравится

4 комментария

Добрый день.

 

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

Пользовательских средств для реализации фильтра по умолчанию нет в коробке. Только разработкой.

 

Необходимо переопределить initQueryFilters
initQueryFilters: function(esq) {
                    this.callParent(arguments);
                    esq.filters.add("ConnectionType",
                            Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "ConnectionType",1));
                    }

 

Подобные вопросы рассматривались на портале, ссылки ниже:

https://community.creatio.com/questions/how-filter-section-list-records…

https://community.terrasoft.ru/questions/kak-predustanovit-uslovie-v-fi…

https://community.terrasoft.ru/questions/vidimost-sotrudnikov-v-kontakt…

https://community.creatio.com/questions/default-filter-section

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

Вы можете подсмотреть реализацию тут:
DocListInConditionPageV2
Там увидите подключение контейнера FilterProperties, в который подгружается FilterEditModule

Литвинко Павел,

Видимо, в текущей версии нет этого файла :( не могли бы поделиться его листингом?

Вадим Курунов пишет:

define("DocListInConditionPageV2", ["FilterEditModule"],
	function() {
		return {
			entitySchemaName: "DocListInCondition",
			attributes: {
				/**
				 * Filtration object schema name.
				 */
				"FilterEntitySchemaName": {
					"dataValueType": this.Terrasoft.DataValueType.TEXT,
					"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
					"dependencies": [{
						"columns": ["DocumentListStage"],
						"methodName": "updateFilterModule"
					}]
				}
			},
			mixins: {},
			diff: /**SCHEMA_DIFF*/[
				{
					"operation": "insert",
					"name": "Document",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"dataValueType": Terrasoft.DataValueType.LOOKUP,
						"value": {"bindTo": "Document"},
						"layout": {
							"column": 0,
							"row": 0,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "DocListGroup",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"dataValueType": this.Terrasoft.DataValueType.ENUM,
						"value": {"bindTo": "DocListGroup"},
						"layout": {
							"column": 0,
							"row": 1,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "DocumentListStage",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"dataValueType": Terrasoft.DataValueType.ENUM,
						"value": {"bindTo": "DocumentListStage"},
						"layout": {
							"column": 0,
							"row": 2,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "ParticipantRole",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"dataValueType": Terrasoft.DataValueType.ENUM,
						"value": {"bindTo": "ParticipantRole"},
						"layout": {
							"column": 0,
							"row": 3,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "DocumentType",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"dataValueType": Terrasoft.DataValueType.ENUM,
						"value": {"bindTo": "DocumentType"},
						"layout": {
							"column": 0,
							"row": 4,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "SysModuleReport",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"dataValueType": Terrasoft.DataValueType.LOOKUP,
						"value": {"bindTo": "SysModuleReport"},
						"layout": {
							"column": 0,
							"row": 5,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "IsRequired",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"layout": {
							"column": 0,
							"row": 6,
							"colSpan": 10
						}
					}
				},
				{
					"operation": "insert",
					"name": "FilterProperties",
					"parentName": "Header",
					"propertyName": "items",
					"values": {
						"id": "FilterProperties",
						"itemType": Terrasoft.ViewItemType.CONTAINER,
						"items": [],
						"layout": {
							"column": 15,
							"row": 0,
							"colSpan": 9,
							"rowSpan": 12
						}
					}
				},
				{
					"operation": "remove",
					"name": "actions"
				}
			]/**SCHEMA_DIFF*/,
			messages: {
				/**
				 * Subscription on filter change.
				 */
				"OnFiltersChanged": {
					mode: Terrasoft.MessageMode.BROADCAST,
					direction: Terrasoft.MessageDirectionType.SUBSCRIBE
				},
 
				/**
				 * Subscription on receiving of filter module configuration object.
				 */
				"GetFilterModuleConfig": {
					mode: Terrasoft.MessageMode.PTP,
					direction: Terrasoft.MessageDirectionType.SUBSCRIBE
				},
 
				/**
				 * Publishing message about setting filter module.
				 */
				"SetFilterModuleConfig": {
					mode: Terrasoft.MessageMode.BROADCAST,
					direction: Terrasoft.MessageDirectionType.PUBLISH
				}
			},
			methods: {
 
				/**
				 * Returns Id of filtration module.
				 * @protected
				 * @return {String} Filtration module Id.
				 */
				getFilterEditModuleId: function() {
					return this.sandbox.id + "_ExtendedFilterEditModule";
				},
 
				/**
				 * Loads filter module.
				 * @protected
				 */
				loadFilterModule: function() {
					var moduleId = this.getFilterEditModuleId();
					this.sandbox.subscribe("OnFiltersChanged", this.onFiltersChanged, this, [moduleId]);
					this.sandbox.subscribe("GetFilterModuleConfig", this.onGetFilterModuleConfig, this, [moduleId]);
					this.sandbox.loadModule("FilterEditModule", {
						renderTo: "FilterProperties",
						id: moduleId
					});
					this.set("FilterModuleLoaded", true);
				},
 
				/**
				 * Sets FilterConfig by filter that was received from filtration module.
				 * @param {Object} args Object with serialized filter.
				 * @protected
				 */
				onFiltersChanged: function(args) {
					this.hideBodyMask();
					this.setFilterConfig(args.serializedFilter);
				},
 
				/**
				 * Sets field FilterConfigand flag HasFilters in objects.
				 * @param {String} serializedFilter Serialized filter.
				 * @private
				 */
				setFilterConfig: function(serializedFilter) {
					this.set("FilterConfig", serializedFilter);
					var filters = this.Terrasoft.deserialize(serializedFilter);
					this.set("HasFilters", this.Ext.isEmpty(filters) ? false : filters.getCount() > 0);
				},
 
				/**
				 * Returns config for filtration module.
				 * @protected
				 * @return {Object} Cofiguration object.
				 */
				onGetFilterModuleConfig: function() {
					return {
						rootSchemaName: this.get("FilterEntitySchemaName"),
						filters: this.get("FilterConfig")
					};
				},
 
				/**
				 * Unloads filter module.
				 * @protected
				 */
				unloadFilterModule: function() {
					var moduleId = this.getFilterEditModuleId();
					this.sandbox.unloadModule(moduleId);
					this.set("FilterModuleLoaded", false);
				},
 
				/**
				 * Creates Terrasoft.EntitySchemaQuery instance for receiving SysEntitySchemaName of FilterEntity that
				 * is specified in DocumentListStage record.
				 * @protected
				 * @return {Terrasoft.EntitySchemaQuery} Terrasoft.EntitySchemaQuery instance with initialized
				 * rootSchemaName and columns
				 */
				getEsqForInitFilterEntityByDocListStage: function() {
					var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
						rootSchemaName: "DocumentListStage"
					});
					esq.addColumn("FilterEntity.SysEntitySchemaName", "FilterEntitySchemaName");
					return esq;
				},
 
				/**
				 * Initializes FilterEntitySchemaName property depending on the DocumentListStage property and calls
				 * callback function.
				 * @protected
				 * @param {Function} callback The callback function.
				 * @param {Object} scope The scope of callback function.
				 */
				initFilterEntity: function(callback, scope) {
					var docListStage = this.get("DocumentListStage");
					if (docListStage && docListStage.value) {
						this.initFilterEntityByDocListStage(docListStage.value, callback, scope);
					} else {
						this.set("FilterEntitySchemaName", null);
						this.Ext.callback(callback, scope);
					}
				},
 
				/**
				 * Receives SysEntitySchemaName of FilterEntity that is specified in DocumentListStage record,
				 * sets is to FilterEntitySchemaName property and calls callback funcion.
				 * @protected
				 * @param {Guid} docListStageId Id of document list stage record.
				 * @param {Function} callback The callback function.
				 * @param {Object} scope The scope of callback function.
				 */
				initFilterEntityByDocListStage: function(docListStageId, callback, scope) {
					var esq = this.getEsqForInitFilterEntityByDocListStage();
					esq.getEntity(docListStageId, function(result) {
						var entity = result.success ? result.entity : null;
						this.initFilterEntityByDocListStageCallback(entity);
						this.Ext.callback(callback, scope);
					}, this);
				},
 
				/**
				 * Processes result of query in initFilterEntityByDocListStage method.
				 * @protected
				 * @param {Object} entity Object with entity that returned by query.
				 */
				initFilterEntityByDocListStageCallback: function(entity) {
					var entitySchemaName = !this.Ext.isEmpty(entity)
						? entity.get("FilterEntitySchemaName")
						: null;
					this.set("FilterEntitySchemaName", entitySchemaName);
				},
 
				/**
				 * Updates filter module. Clears filter if filter object is changed.
				 * @protected
				 * @param {Function} callback The callback function.
				 * @param {Object} scope The scope of callback function.
				 */
				updateFilterModule: function(callback, scope) {
					this.showBodyMask();
					this.initFilterEntity(function() {
						var filterEntitySchemaName = this.get("FilterEntitySchemaName");
						if (this.Ext.isEmpty(filterEntitySchemaName)) {
							if (this.get("FilterModuleLoaded")) {
								this.setFilterConfig(null);
								this.unloadFilterModule();
							}
							this.hideBodyMask();
						} else if (!this.get("FilterModuleLoaded")) {
							this.loadFilterModule();
						} else {
							var config = this.get("IsEntityInitialized") ? null : this.get("FilterConfig");
							this.setFilterModuleConfig(filterEntitySchemaName, config);
						}
						this.Ext.callback(callback, scope);
					}, this);
				},
 
				/**
				 * Publishes message SetFilterModuleConfig for filtration module.
				 * @param {String} entitySchemaName Name of object that conditions will be setting for.
				 * @param {String} filterConfig Serialized filter.
				 * @protected
				 */
				setFilterModuleConfig: function(entitySchemaName, filterConfig) {
					var moduleId = this.getFilterEditModuleId();
					this.sandbox.publish("SetFilterModuleConfig", {
						rootSchemaName: entitySchemaName,
						filters: filterConfig
					}, [moduleId]);
				},
 
				/**
				 * @inheritdoc Terrasoft.BasePageV2#onEntityInitialized
				 * @overridden
				 */
				onEntityInitialized: function() {
					this.callParent(arguments);
					this.updateFilterModule();
				},
 
				/**
				 * @inheritdoc Terrasoft.BasePageV2#onDiscardChangesClick
				 * @overridden
				 */
				onDiscardChangesClick: function() {
					if (this.isNew) {
						this.sandbox.publish("BackHistoryState");
						return;
					}
					this.set("IsEntityInitialized", false);
					this.loadEntity(this.get("Id"), function() {
						this.updateButtonsVisibility(false, {
							force: true
						});
						this.initMultiLookup();
						this.updateFilterModule(function() {
							this.set("IsEntityInitialized", true);
							this.discardDetailChange();
						}, this);
					}, this);
					if (this.get("ForceUpdate")) {
						this.set("ForceUpdate", false);
					}
				}
			}
		};
	});

 

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

Требуется создать на пункте левого меню Проекты счётчик доступных текущему пользователю проектов.

Под доступными подразумеваются те проекты, которые удовлетворяют следующим условиям (фиксированным фильтрам раздела + права + статусы):

Ответственный = текущий пользователь

И

текущий пользователь имеет права на чтение

И

Состояние проекта не равно (Завершён, Отменён)

 

Выглядеть должно следующим образом.

Я начинающий разработчик и не очень понимаю как именно это реализовать. Была идея создать визуальны модуль с счётчиком, но пока не понимаю как это сделать. Уже написан вэб-сервис, который возвращает доступное количество проектов, но пока нет понимая откуда его вызвать и как установить эти счётчики.

 

Нравится

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

Не факт что туда можно влезть. Левую панель с разделами отрисовывает модуль SideBarModule.

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

Уже есть настроенный показатель «Активных проектов», можно изменить его условие фильтрации:

Или ещё проще, настроить динамическую группу с нужным фильтром, включить в разделе итог «Отображать количество записей» и при нахождении внутри группы над реестром будет видно интересующее число.

Зверев Александр, Спасибо за предложение, но всё-таки мне требуется выводить это число в панели разделов

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

Динар, кажется, придумал ещё один способ.

Из JS доступна структура Terrasoft.configuration.ModuleStructure, где хранится информация по разделам, в том числе и названия. Если там вручную из консоли браузера сменить название, дописав цифру, то при обновлении перечня разделов, например, при смене рабочего места, она появится. Можно менять её программно, а потом вызывать перестройку списка разделов, как при смене рабочего места. Эта структура генерируется на серверной стороне в схеме ConfigurationSectionHelper.

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

Пытаюсь вызывать alert('Hello') на каждой странице. Получилось пока только на конкретной странице создав замещающий клиентский модуль и наследуясь от SalesEnterpriseSoftkey_ENU. Как можно сделать этот алерт на всех страницах,  включая авторизацию и другие?

Нравится

1 комментарий

Андрей, можно вообще добавить свой скрипт в системную настройку GoogleTagManagerScript («Скрипт для Google Tag Manager»), так он будет срабатывать после логина или при загрузке страницы в новой вкладке.

При помощи этого способа встроили в 7.Х голосовалку от Hotjar:

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

В клиентской схеме редактирования добавлен модуль. В схеме модуля есть метод, который необходимо заместить. Каким образом это можно реализовать?

Нравится

1 комментарий
Лучший ответ

Вы можете по аналогии с существующим модулем реализовать свой клиентский модуль с нужным методом.

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

Вы можете по аналогии с существующим модулем реализовать свой клиентский модуль с нужным методом.

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

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

Добрый день.
Есть Данные, хранящиеся в json-строке
Есть Объект, со структурой полей соответствующей Данным в json.
Есть Модуль с DataGrid, в котором нужно отобразить реестр записей.
Наполняю коллекцию GridData: 
 

prepareDataGridViewModule: function(dataList){
    //Наполнить GridData
    var gridData = this.get("GridData");
    var entityConfig = this.getEntityConfig(this.$MasterEntityName);
    this.Terrasoft.each(dataList, function(item) {
        var itemData = Ext.JSON.decode(item.Data);
        var itemModel = this.Ext.create("Terrasoft.BaseViewModel", {
              columns: entityConfig.columns, //Коллекция полей Объекта
              values: itemData   //Коллекция значений полей
         });
         gridData.add(item.Id, itemModel);
      }, this);
}

В итоге получаю отображение: 
https://yadi.sk/i/XUkp2kMCWWB4KQ

Кто сталкивался?
Как можно наполнить плиточное представление реестра в каждой строке своими динамическими полями?

Нравится

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

Игорь, добрый день!

Вы можете разработать формирование всей информации на уровне базы данных в представление, по которому в конфигурации создан объект. Как работать с JSON в MS SQL, описано в этой статье.

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

Игорь, эта логика самостоятельно разработана Вами, поэтому причину такого её поведения можете установить только Вы, например, применив отладку. 

Перефразирую:
В каком виде я должен передать свою коллекцию значений и полей в GridData, чтобы Базовыми средствами отрисовать поля реестра?

Базовыми средствами колонки и их значения берутся из объекта, с которым связан раздел, а не передаются отдельно. Либо используйте представление, либо обычную таблицу с наполнением данными программно.

Попробуйте найти раздел или дополнение, в котором реализовано подобное тому, что Вы хотите получить. Возможно, что-то похожее на раздел планирования.

Я и нашёл. в LocalDuplicateSearchPageV2 и его миксине DuplicatesSearchUtilitiesV2, где в методе loadElasticDuplicates в модель реестра передаются поля (columns) и значения (values).
В итоге в реестре глобального поиска строки реестра отображаются корректно с набором полей и значений, а в моём модуле в строках полоски.

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

Ошибок нет. я бы с удовольствием протестировал.
Только не могу понять какой метод обрабатывает передаваемую коллекцию и отрисовывает реестр.

Произведите отладку Вашего кода и работающего на странице дублей. Также Вы можете заказать такие доработки у компаний-партнёров.

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

Ошибка при сохранении клиентской схемы: Ошибка сохранения: Элемент <Название модуля> не найден.

Данное поведение встречается на версии 7.14.3

1.При создании нового модуля/миксина
2. При переименовании клиентской схемы (детали) после создания мастером деталей

 

Нравится

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

Здравствуйте! Попробуйте сгенерировать коды для данного модуля и скомпилировать сборку затем перелогинится в системе с очисткой кэша в браузера. Мне такие действия помогали. Если локально система развернута, помогало еще перезапуск пула в IIS.

Помогла фиксация в SVN с последующим восстановлением из хранилища.
Но что-то мне подсказывает, что это не совсем корректное поведение. И появилось оно на версии 7.14.3

Добрый день, Игорь.

Для временного устранения надо в Web.config загрузчика, выключить фичу Feature-OptimizeManagersSynchronization = false и после переименования сохранять два раза.
При первом сохранении сообщение будет появляться, после второго ошибки не будет, а схема будет сохранена.
В новых версиях будет предоставлено решение такого поведения системы.

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

Коновалов Игорь,

Коновалов Игорь пишет:
И появилось оно на версии 7.14.3

Замечала и на версии 7.14.2, а вот раньше такого не помню. 

Мотков Илья,

Повторилось на  версии  7.14.0, 7.14.2 и 7.13.3 при этом ключа Feature-OptimizeManagersSynchronization ни в одной из перечисленных версий нет.

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

Привет всем !
Возник такой вопрос, как сделать модальное окно с нужными полями и чекбоксами ?
нужно что то вроде:
Ответственному - (Логический тип), Время - (Дата/Время) 

Нашёл различные статьи, но там написано как сделать просто окно или вообще что то другое или вообще не чего, вообщем всё не то.
Я так понимаю нужно сделать что то вроде ModalBox после чего передать параметры поля размер и т.д . Но как это сделать не знаю.
Если кто знает подскажите.

Нравится

3 комментария
Лучший ответ

Тут расписано как создать окно, в нем добавляете нужные вам атрибуты (столбцы) и задаете в diff их прорисовку.

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

Тут расписано как создать окно, в нем добавляете нужные вам атрибуты (столбцы) и задаете в diff их прорисовку.

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

Григорий Чех,

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

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

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

Добрый день. Я так понял что есть скрипт, который при изменении количества продукта в графике поставок и оплат, при связанном счете к этому шагу, заново пересчитывает сумму и количество продукта в связанном счете. Подскажи в каком модуле лежат этот скрипт и как он называется

Нравится

1 комментарий

День добрый! 

Скрипт по апдейту значений из продукта в заказе продуктов в счете (через график поставок и оплат) лежит в схеме OrderAmountHelper.

Удачи!

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

Добрый день, коллеги!
Помогите решить следующую задачу:

bpm'online 7.5
Мне нужно создать модуль, который будет являть собой страницу с таблицей. Таблицу необходимо заполнить данными, сгенерированными в том же модуле (например, статично заданные демо-данные; в дальнейшем будет выполняться запрос к веб-сервису для получения данных).
На странице, например, контрагента я создам вкладку, и в эту вкладку мне нужно загрузить этот модуль с таблицей.

Нравится

4 комментария

Здравствуйте, Евгений!
В целом Вам необходимо создать модуль, расширяющий BaseSchemaModuleV2, в который будет загружаться страница с содержимым. Затем загрузить этот модуль в контейнер. Пример модуля:

define("ModuleName", ["BaseSchemaModuleV2"], function() {
 
	Ext.define("Terrasoft.configuration.ModuleName", {
		alternateClassName: "Terrasoft.ModuleName",
		extend: "Terrasoft.BaseSchemaModule",
 
		/**
		 * Инициализирует название схемы.
		 * @protected
		 * @overridden
		 */
		initSchemaName: function() {
			this.schemaName = "PageName";
		},
 
 
		/**
		 * Заменяет последний элемент в цепочке состояний, если его идентификатор модуля отличается от текущего.
		 * @protected
		 * @overridden
		 */
		initHistoryState: Ext.emptyFn
 
	});
	return Terrasoft.ModuleName;
});

На странице "PageName" необходимо реализовать отображение таблицы.
Загружать модуль в контейнер можно следующим образом:

var schemaName = "PageName";
var pageId = this.sandbox.id + schemaName;
this.showBodyMask();
this.sandbox.loadModule("ModuleName", {
	renderTo: "ModuleNameContainer", //Id контейнера
	id: pageId,
	keepAlive: true
});

Андрей, спасибо за ответ. К сожалению, с указанным способом возникли затруднения, и я реализовал модуль по-другому:

q1

define("VisualModule", ["VisualModuleResources", "ViewUtilities", "ServiceHelper", "BaseModule", "ContainerList", "css!VisualModule"],
    function(resources, ViewUtilities, ServiceHelper) {
        Ext.define("Terrasoft.configuration.VisualModule", {
            alternateClassName: "Terrasoft.VisualModule",
            extend: "Terrasoft.BaseModule",
 
            Ext: null,
            sandbox: null,
            Terrasoft: null,
 
            getContainer: function() {
                var itemsContainer = ViewUtilities.getContainerConfig("itemsContainer",
                    ["items-container-class"]);
                itemsContainer.items.push({
                    className: "Terrasoft.Button",
                    style: Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                    classes: {textClass: ["cancel-all-class"]},
                    caption: "AddToCollection",
                    click: {bindTo: "onButtonClick"}
                });
                itemsContainer.items.push({
                    className: "Terrasoft.ContainerList",
                    id: "CON1",
                    idProperty: "Id",
                    selectors: {wrapEl: "#CON1"},
                    collection: {bindTo: "itemsCollection"},
                    defaultItemConfig: this.getItemConfig()
                });
                return itemsContainer;
            },
            getItemConfig: function() {
                var itemConfig;
                itemConfig = ViewUtilities.getContainerConfig("ItemContainer",
                    ["item-container"]);
                var itemTopContainer = ViewUtilities.getContainerConfig("itemTopContainer",
                    ["item-top-container"]);
 
                itemTopContainer.items.push({
                    className: "Terrasoft.Label",
                    caption: {bindTo: "displayValue"},
                    classes: {labelClass: ["button-caption-labelClass"]}
                });
                itemConfig.items.push(itemTopContainer);
 
                return itemConfig;
            },
            getView: function() {
                var viewItems = [];
                var textEdit = {
                    className: "Terrasoft.TextEdit",
                    width: 100,
                    value: {"bindTo": "textValue"}
                };
                var bindedContainer = this.getContainer();
 
                viewItems.push(textEdit);
                viewItems.push(bindedContainer);
 
                return this.Ext.create("Terrasoft.Container", {
                    id: "mainContainer",
                    selectors: {wrapEl: "#mainContainer"},
                    classes: {wrapClassName: ["main-container-style"]},
                    items: viewItems
                });
            },
 
            getViewModel: function() {
                var scope = this;
                var sandbox = scope.sandbox;
                var Terrasoft = scope.Terrasoft;
                var viewModel = Ext.create("Terrasoft.BaseViewModel", {
                    values: {
                        textValue: "Some text",
                        itemsCollection: new Terrasoft.Collection()
                    },
                    methods: {
                        onButtonClick: function(){
                            var collection = this.get("itemsCollection");
                            var item = { value: "Id1", displayValue: "Name1"};
                            this.decorateItem(item)
                            collection.add(this.newGuid(), item);
 
                        },
                        decorateItem: function(item) {
                            item.sandbox = sandbox;
                            item.Terrasoft = Terrasoft;
                        },
                        newGuid: function() {
                            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
                                function(c) {
                                    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                                    return v.toString(16); })
                        }
                    }
                });
                viewModel.Ext = this.Ext;
                viewModel.Terrasoft = this.Terrasoft;
                viewModel.sandbox = this.sandbox;
                return viewModel;
            },
 
            render: function(renderTo) {
                var view = this.getView();
                var viewModel = this.getViewModel();
                view.bind(viewModel);
                view.render(renderTo);
            }
        });
        return Terrasoft.VisualModule
    });

Загружаю модуль так:

var schemaName = "PageName";
var pageId = this.sandbox.id + schemaName;
this.sandbox.loadModule("VisualModule", {
renderTo: "SmrMediaplanPage6Tab", //Id контейнера
id: pageId,
keepAlive: true
});

На страницу успешно загружается модуль, и даже текстовое поле получает привязку:
2

В коде добавлен контейнер типа Terrasoft.ContainerList, и сделана привязка к коллекции itemsCollection из ViewModel (itemsCollection: new Terrasoft.Collection())

При попытке добавить элемент в эту коллекцию:

var collection = this.get("itemsCollection");
var item = { value: "Id1", displayValue: "Name1"};
this.decorateItem(item)
collection.add(this.newGuid(), item);

происходит ошибка в ContainerList.js:
не видит метода get()

123

Примеры кода я копировал из стандартных модулей, и там такой проблемы само собой не возникает. Скорее всего, я ещё что-то не учёл, но пока не понимаю что.

Как правильно забиндить ContainerList?

День добрый!
Так а откуда в Вашем item должен появиться метод get?
По идее, item должен быть экземпляром класса Terrasoft.BaseViewModel, а у Вас - это просто объект, в который добавлены несколько свойств.
Попробуйте так:

var item = this.Ext.create("Terrasoft.BaseViewModel", {
	values: {
		Id: "Id1",
		Name: "Name1"
	}
});

И еще проверьте, есть ли значение в this.idProperty. Там должна быть строка с названием колонки-идентификатора.
Вместо вот этого страха:

newGuid: function() {
                            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
                                function(c) {
                                    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                                    return v.toString(16); })
                        }

Можно использовать метод Terrasoft.generateGUID().

Андрей, спасибо, это то, что нужно! :)
Сделал item как Terrasoft.BaseViewModel, и всё получилось.

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

А знаете ли вы, уважаемые любители быстро перенести готовый стандартный модуль из одной системы в другую в замечательный модуль Custom, что теперь такая возможность у вас пропала?
Не будем говорить о переносе Проектов, Документов и прочая в Sales, так как это нехорошо:cool:, и необходимость в таком разделе должна толкать покупателя к приобретению более дорогого продукта, а не стимулировать программистов к работе.

А приведем пример законопослушный вполне - берем у клиента старенький Terrasoft 3.2.1 x25, в котором был модуль "Склад" - простенький совсем по нынешним меркам, но все же был и использовался. И попробуем перевести такого клиента на 3.4 XRM, в котором склада понятное дело нету. Ну нету и нету, наше дело сервисы выгрузить да в Custom залить, вот он и появится - но не тут то было. Уже при попытке сохранения сервиса таблицы tbl_OfferingMovement всякого хитреца ждет сообщение, что "Service 'tbl_OfferingMovement' must be located only in the module 'OfferingMovement'".
В итоге запрос не запустится, и так далее... Путь решения в общем-то простой, но требует усидчивости и внимательности - переименовываем таблицу в tbl_BestOfferingMovement:smile: и затем все упоминания, связи... в итоге получаем загруженный работающий модуль.
Или об этой особенности не знал только я? :wink:

Нравится

Поделиться

1 комментарий

Кстати в нелегком труде переименования поможет прекрасная бесплатная утилита от http://tr.infortech.ru/ под названием @Text Replacer.
Выгружаем все сервисы несчастного модуля в XML в некоторую папку, и запускаем @Text Replacer, говорим ему название этой папки и запускаем автоматическую замену по содержимому XML, например "Movement" на "BestMovement".
В этом случае поменяется и USI, и названия таблицы, и запросы подправятся, и так далее... останется только загрузить все сервисы обратно и скрипты поправить - уже в Администраторе, поиском/заменой "Movement" на "BestMovement" штатными средствами. Так будут исправлены названия обработчиков событий, переменные, названия сервисов, упомянутых в скриптах.

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