Добрый день.

Как мне добавить в элемент лукапа деталь с выбором из справочника?

Прикрепленные файлы

Нравится

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

Пример из нашей базы знаний (стиль сохранён).



Как запилить справочник со страницей редактирования И деталью в нагрузку.

1. Делаем деталь со страницей редактирования через мастер;

2. Создаем Schema of the Edit Page в конфигураторе, вставляем туда разметку, которую должна отображать наша страница редактирования детали:

 

define("UsrCompanyStructureTypePageV2", [],
    function() {
        return {
            entitySchemaName: "UsrCompanyStructureType",
            details: /**SCHEMA_DETAILS*/{
                "CompanyStructureDetail": {
                    "schemaName": "UsrCompanyStructureMemberDetailV2",
                    "filter": {
                        "masterColumn": "Id",
                        "detailColumn": "UsrType"
                    }
                }
            }/**SCHEMA_DETAILS*/,
            attributes: {},
            methods: {},
            rules: {},
            userCode: {},
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "insert",
                    "name": "Name",
                    "values": {
                        "layout": {
                            "colSpan": 12,
                            "rowSpan": 1,
                            "column": 0,
                            "row": 0,
                            "layoutName": "Header"
                        },
                        "bindTo": "Name"
                    },
                    "parentName": "Header",
                    "propertyName": "items",
                    "index": 0
                },
                {
                    "operation": "insert",
                    "name": "CompanyStructureDetail",
                    "values": {
                        "itemType": 2
                    },
                    "parentName": "GeneralInfoTab",
                    "propertyName": "items",
                    "index": 1
                }
            ]/**SCHEMA_DIFF*/
        };
    });

3. Регистрируем страницу редактирования в БД через процедуру:

EXEC [dbo].[tsp_RegisterPage]
        @ModuleEntityName = N'UsrCompanyStructureType ',
        @PageName = N'UsrCompanyStructureTypePageV2',
        @TypeColumnUId = NULL,
        @TypeValue = NULL,
        @AddMenuCaptionRus = 'Добавить',
        @AddMenuCaptionEng = 'Add',
        @CardHeaderCaptionRus = NULL,
        @CardHeaderCaptionEng = NULL

Если пропадает кнопка Добавить надо создать в SysModuleEditLcz с текстом что будет отображаться на кнопке:

insert into SysModuleEditLcz (id, CreatedOn, RecordId, ColumnUId, SysCultureId, Value)
select newid(), getdate(), 'D716F900-239E-44F3-98A8-DBBF3517FB9A', 'A19BF4BF-E22B-49B5-B6E0-918FF6290020', 'A5420246-0A8E-E111-84A3-00155D054C03', 'New'

RecordID – ID записи из SysModuleEdit нашей зарегистрированной страницы. Можно найти по CreatedOn (т.к. регистрация страницы по идее есть последняя операция то это будет последняя запись в таблице) или через имя схемы объекта по связи SysModuleEntityId – SysEntitySchemaUId из SysSchema

ColumnID – какая-то внутренняя константа, откуда берется не вникал

SysCultureID – ID языка на которой будет отображаться запись

Value – сам текст на кнопке

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

Пример из нашей базы знаний (стиль сохранён).



Как запилить справочник со страницей редактирования И деталью в нагрузку.

1. Делаем деталь со страницей редактирования через мастер;

2. Создаем Schema of the Edit Page в конфигураторе, вставляем туда разметку, которую должна отображать наша страница редактирования детали:

 

define("UsrCompanyStructureTypePageV2", [],
    function() {
        return {
            entitySchemaName: "UsrCompanyStructureType",
            details: /**SCHEMA_DETAILS*/{
                "CompanyStructureDetail": {
                    "schemaName": "UsrCompanyStructureMemberDetailV2",
                    "filter": {
                        "masterColumn": "Id",
                        "detailColumn": "UsrType"
                    }
                }
            }/**SCHEMA_DETAILS*/,
            attributes: {},
            methods: {},
            rules: {},
            userCode: {},
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "insert",
                    "name": "Name",
                    "values": {
                        "layout": {
                            "colSpan": 12,
                            "rowSpan": 1,
                            "column": 0,
                            "row": 0,
                            "layoutName": "Header"
                        },
                        "bindTo": "Name"
                    },
                    "parentName": "Header",
                    "propertyName": "items",
                    "index": 0
                },
                {
                    "operation": "insert",
                    "name": "CompanyStructureDetail",
                    "values": {
                        "itemType": 2
                    },
                    "parentName": "GeneralInfoTab",
                    "propertyName": "items",
                    "index": 1
                }
            ]/**SCHEMA_DIFF*/
        };
    });

3. Регистрируем страницу редактирования в БД через процедуру:

EXEC [dbo].[tsp_RegisterPage]
        @ModuleEntityName = N'UsrCompanyStructureType ',
        @PageName = N'UsrCompanyStructureTypePageV2',
        @TypeColumnUId = NULL,
        @TypeValue = NULL,
        @AddMenuCaptionRus = 'Добавить',
        @AddMenuCaptionEng = 'Add',
        @CardHeaderCaptionRus = NULL,
        @CardHeaderCaptionEng = NULL

Если пропадает кнопка Добавить надо создать в SysModuleEditLcz с текстом что будет отображаться на кнопке:

insert into SysModuleEditLcz (id, CreatedOn, RecordId, ColumnUId, SysCultureId, Value)
select newid(), getdate(), 'D716F900-239E-44F3-98A8-DBBF3517FB9A', 'A19BF4BF-E22B-49B5-B6E0-918FF6290020', 'A5420246-0A8E-E111-84A3-00155D054C03', 'New'

RecordID – ID записи из SysModuleEdit нашей зарегистрированной страницы. Можно найти по CreatedOn (т.к. регистрация страницы по идее есть последняя операция то это будет последняя запись в таблице) или через имя схемы объекта по связи SysModuleEntityId – SysEntitySchemaUId из SysSchema

ColumnID – какая-то внутренняя константа, откуда берется не вникал

SysCultureID – ID языка на которой будет отображаться запись

Value – сам текст на кнопке

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

Владимир Соколов,

Большое спасибо за информацию. Есть один момент. У меня отсутствует хранимка с таким названием. Постарался найти запрос на создание, но те, что удалось откопать, невалидны из-за измененных столбцов в таблице SysModuleEditLcz.

В этой таблице никакие изменения я, конечно, не делал)

Вроде, устанавливали. Вот здесь есть обсуждение про неё 

https://community.terrasoft.ua/questions/sozdanie-detali-s-neskolkimi-tipami-i-vypadausim-spiskom-na-knopke-add-dla-bpm-75

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

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

фильтр из детали, указывается лишь кол-во и датаИзображение удалено.

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

Изображение удалено.

Нравится

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

Доброе утро.

Все верно, так и должно быть.

В колонке выбираете количество, после этого в самой области фильтра 'количество' можно сменить на 'существует' или 'не существует' и в области подфильтра уже работать с табличкой детали и настраивать нужные фильтры.

Более подробно о том, как построить exist-фильтр можно почитать на Академии по ссылке (подтема 'Установка агрегирующего фильтра').

Доброе утро.

Все верно, так и должно быть.

В колонке выбираете количество, после этого в самой области фильтра 'количество' можно сменить на 'существует' или 'не существует' и в области подфильтра уже работать с табличкой детали и настраивать нужные фильтры.

Более подробно о том, как построить exist-фильтр можно почитать на Академии по ссылке (подтема 'Установка агрегирующего фильтра').

Алла Савельева,

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

Касымов Сакен,

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

Нашел другой способ, создал вьюшку в БД и объект, поставил галочку в "Представление в БД"в этой вьюшке есть есть значения с "NULL" (это не проблема?)

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

Касымов Сакен,

А какой график нужно получить в итоге?

Возможно, неправильно сделали представление.

Посмотрите в SQL Management Studio, какие данные возвращает Ваше представление.

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

Превратить Null в пустую или какую угодно строку можно функцией IsNull со вторым параметром.

Также при создании пользовательских представлений для корректной их работы необходимо наследование от схемы BaseEntity, где есть стандартные колонки. 

Зверев Александр пишет:

Также при создании пользовательских представлений для корректной их работы необходимо наследование от схемы BaseEntity, где есть стандартные колонки

Не согласна с этим утверждением.

Все зависит от того для реализации какой функциональности создается то или другое представление. 

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

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

Какая деталь в Контакте отвечает за email, отправленные через Terrasoft?

Почему-то email, отправленные через email-рассылки, не добавляеются в Активность email.

Интересно видеть, в каких email-рассылках и кампаниях учавствует Контакт

Нравится

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

На закладке История в карточке контакта найдете обе детали

На закладке История в карточке контакта найдете обе детали

Владимир Соколов, Я удалил деталь Рассылки Email. Подскажите, что у вас стоит в Колонка детали и в Колонка объекта у этой детали?

Александр, там так:

Зверев Александр, Спасибо!

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

Добрый день, коллеги.

Появилась необходимость произвести следующую доработку: на страницу Заказа вывести деталь, которая будет показывать все заказы, у которых Контакт такой же, как и на отображаемой страницу, но к тому же чтобы была возможность вывода продуктов из каждого заказа, по аналогии с деталью Структура в Проектах. Конечно, аналогия не совсем прямая, в Проектах всё завязано только на одном объекте, когда как в поставленной задаче нужно в первом "слое" выводить записи из Заказов, в во втором "слое" - Продукты в Заказе. Кто-нибудь сталкивался с подобным заданием или разбирал этот функционал? Уже изучил схемы ProjectStructureDetailV2, BaseProjectPageV2 и ProjectUtilities. Также нашёл схему HierarchicalProjectUtilities, там, кажется, находится нечто полезное, но я вообще не нашёл связи между этой схемой и кодом, который ответственен за деталь Структура. Меня более всего интересует сам механизм получения списка того, что нужно отобразить в детали, возможно придётся писать полностью свою логику сборки этого списка, но куда этот составленный список применить - мне не понятно. Будет полезно всё - от указания всех схем, которые участвуют в корректной отрисовке Структуры до принципиального описания как это всё работает и идей, как возможно прикрутить ещё один левый объект. Заранее спасибо!

 

Нравится

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

Если деталь Read-only, то делали View с полем Parent и использовали модуль "Hierarchy list view for creatio" из marketplace

 

Если деталь Read-only, то делали View с полем Parent и использовали модуль "Hierarchy list view for creatio" из marketplace

 

Владимир Соколов, не могли бы вы уточнить, каким образом вы произвели данную доработку именно для двух разных объектов в одной детали? На что должно ссылаться поле Parent в представлении, какой именно раздел преобразовывали в представление для детали? Я имею в виду, модуль всё равно работает только с одним объектом, в их примере они настраивают древовидное отображение дочерних договоров для самих же договоров

Видимо, Владимир имеет в виду создание с нуля view, которая берёт данные из нескольких таблиц и формирует в древовидную структуру со ссылками из одних записей view на другие в поле ParentId.

Если первичный ключ записи в этой view нельзя взять из однозначно соответствующей записи одной из таблиц, его можно также формировать программно, например, взяв первую половину Guid из Id записи одного раздела и вторую половину — из другого. Или md5-хэш от других полей, как в примере тут. Главное, чтобы было полное соответствие Id записей, на которые ссылаются и значений полей-ссылок.

Затем по этому view создать объект и далее его использовать в «Hierarchy list view».

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

Кейс: чек-лист сделан в виде детали на странице звонка. Пользователь всегда хочет видеть список чек-листа сразу полностью развернутым, без кнопки "показать больше".

Подскажите, пожалуйста, как это можно реализовать?

Изображение удалено.

 

 

 

Нравится

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

Можно в своём пакете модифицировать страницу этой детали, задать заведомо большое значение RowCount (например, 100) и, если нужно, отрицательное IsDetailCollapsed, отвечающее за свёрнутость. См. в схеме BaseProcessExecutingDetail:

/**
 * @inheritdoc BaseDetailV2#initDetailOptions
 * @override
 */
initDetailOptions: function() {
	this.set("IsDetailCollapsed", false);
	this.set("RowCount", 20);
},

Также см. статью.

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

Добрый день.

Есть Данные, хранящиеся в 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).

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

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

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

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

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

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

Есть два справочника: "Запрос" и "Расчет к запросам".

В "Запрос" крепится деталь, где указывается поле из второго справочника (см.Рис 1.2.).

 

Как можно через кнопку(JS на клиенте/сама кнопка уже есть) в справочнике "Запрос" узнать Id прикрепленной детали?

Изображение удалено.

Изображение удалено.

 

 

 

 

 

 

 

 

 

Нравится

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

Так в том и дело, что нет разницы сколько на данный момент записей в детали одна или несколько. Все они хранятся в коллекции GridData детали.

Вы уверенны, что эта логика должна отрабатывать на клиентской части?

Т.к. в итоге вам нужно будет делать esq-запрос к всё той же детали  для получения значения поля "Статус(usrStatus)" (т.к. не факт, что в реестре детали выведено поле "Статус(usrStatus)" )

Если всё же на клиентской части, то 

в BasePageV2 есть коллекция this.entitySchemaInfo.details,

И есть метод var detailId = this.getDetailId(detailName);

Вы можете на странице Запроса (где кнопка) создать адресное сообщение (publish)

И при клике на кнопку его отправлять. Адресатом будет detailId.

А в схеме детали с реестом (Расчет) добавить это же сообщение, но уже как подписчика (subscribe).И при получении этого сообщения возвращать this.get("GridData")

 

Вам нужно получить ID детали или Id определённой записи из детали?

Получить Id прикрепленной детали, у неё найти поле "Статус(usrStatus)" и сверить что поле = "Согласован"



Это первый опыт работы с деталями

Т.е. всё же Id записи  "Расчет к запросам" связанный с текущим Запросом?

А кнопка у вас где располагается?

 

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

В справочнике "Запрос"

Дело в том, что деталь может содержать несколько записей. И вам необходимо понимать Id какой именно запись вы хотите получить.

 

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

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

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

Так в том и дело, что нет разницы сколько на данный момент записей в детали одна или несколько. Все они хранятся в коллекции GridData детали.

Вы уверенны, что эта логика должна отрабатывать на клиентской части?

Т.к. в итоге вам нужно будет делать esq-запрос к всё той же детали  для получения значения поля "Статус(usrStatus)" (т.к. не факт, что в реестре детали выведено поле "Статус(usrStatus)" )

Если всё же на клиентской части, то 

в BasePageV2 есть коллекция this.entitySchemaInfo.details,

И есть метод var detailId = this.getDetailId(detailName);

Вы можете на странице Запроса (где кнопка) создать адресное сообщение (publish)

И при клике на кнопку его отправлять. Адресатом будет detailId.

А в схеме детали с реестом (Расчет) добавить это же сообщение, но уже как подписчика (subscribe).И при получении этого сообщения возвращать this.get("GridData")

 

Как вариант можно использовать сообщения например такой сценарий

1)по нажатии вашей кнопки на карточке публикуется сообщение

2) в дели по подписке на сообщение перебираются все строки данных и формируется в массив список id записей у которых статус = согласован. Сформированый массив передается в карточку.

 

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

Добрый день, коллеги. Необходимо чтобы в разделе была сгенерирована деталь с полями (описание, тип оплаты, сумма,  файл (фото_чека.jpg/png/pdf)).

В разделе есть деталь "Файл и ссылка объекта Продажи". Добавляю колонки тип оплаты, сумма. Затем замещаю схему FileDetailV2 и добавляю в него код для того, чтобы была возможность настроить колонки для детали. Настраиваю колонки и они показываются на странице, но заполнить добавленные поля (тип оплаты, сумма) не получается потому что на карточке редактирования их нет (там только стандартные поля Название и описание).

Вопрос: как добавить созданные поля в карточку?

Нравится

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

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

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

Не подскажите, как создать эту карточку?

Артём Иванов Иванович,

в мастере раздела создается новая страница редактирования на первой странице

Натали Вишня,

Это очевидно не то, что мне нужно.

Добавить нужные колонки и отобразить их получилось:

Но какую страницу заместить, чтобы добавить в эту карточку необходимые колонки (сумма) 

Похоже на LinkPageV2. Точно проверить можно, нажав в браузере «Inspect» и посмотрев в HTML-коде.

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

Имеется иерархическая деталь с редактируемым реестром. В ней возникает проблема при сохранении дробного числа. Появляется ошибка Cannot read property 'getAttribute' of null, которая возникает в результате того, что метод GetDomRow возвращает undefined. После этого я не могу больше сохранять дробные числа в реестре и приходится перезагружать страницу. Первое сохранение проходит удачно, хоть и успевает появиться ошибка. В результате чего возникает такая проблема? ниже представлен код детали

define("IDSBRefrigeratorInTMADetail",
    ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities", "ServiceHelper"],
    function (ConfigurationGrid, ConfigurationGridGenerator, ConfigurationGridUtilities, ServiceHelper) {
        return {
            messages: {
                "ReloadRefrigeratorsInTMAGrid": {
                    "mode": Terrasoft.MessageMode.BROADCAST,
                    "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
                }
            },
            entitySchemaName: "IDSBRefrigeratorInTMA",
            attributes: {
                "IsEditable": {
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: true
                }
            },
            mixins: {
                ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
            },
            details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "DataGrid",
                    "values": {
                        "hierarchical": true,
                        "hierarchicalColumnName": "IDSBParent",
                        "className": "Terrasoft.ConfigurationGrid",
                        "generator": "ConfigurationGridGenerator.generatePartial",
                        "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
                        "changeRow": { "bindTo": "changeRow" },
                        "unSelectRow": { "bindTo": "unSelectRow" },
                        "onGridClick": { "bindTo": "onGridClick" },
                        "activeRowAction": { "bindTo": "onActiveRowAction" },
                        "initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
                        "multiSelect": false
                    }
                },
                {
                    "operation": "remove",
                    "name": "AddRecordButton"
                }]/**SCHEMA_DIFF*/,
            methods: {
                generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {
                    this.columnsConfig = columnsConfig;
                    var gridData = this.getGridData();
                    var activeRow = gridData.get(id);
                    var isEditableColumn;
                    if (activeRow.values.IDSBParent === "") {
                        isEditableColumn = this.ParentColumnIsEditable;
                    }
                    else {
                        isEditableColumn = this.ColumnIsEditable;
                    }
                    var gridLayoutItems = [];
                    var currentColumnIndex = 0;
                    Terrasoft.each(columnsConfig, function (columnConfig) {
                        var cellConfig = this.getActiveRowCellConfig(columnConfig, currentColumnIndex);
                        cellConfig.enabled = isEditableColumn(cellConfig.name);
                        if (!cellConfig.hasOwnProperty("isNotFound")) {
                            gridLayoutItems.push(cellConfig);
                        }
                        currentColumnIndex += cellConfig.layout.colSpan;
                    }, this);
                    this.applyBusinessRulesForActiveRow(id, gridLayoutItems);
                    var viewGenerator = Ext.create(this.getRowViewGeneratorClassName());
                    viewGenerator.viewModelClass = this;
                    var gridLayoutConfig = viewGenerator.generateGridLayout({
                        name: this.name,
                        items: gridLayoutItems
                    });
                    rowConfig.push(gridLayoutConfig);
                },
                ParentColumnIsEditable: function (columnName) {
                    return (columnName === "IDSBPlacementPrice" || columnName === "IDSBNumberOfDoors" || columnName === "IDSBProlongation");
                },
                ColumnIsEditable: function (columnName) {
                    return (columnName === "IDSBRBBottlePlan" || columnName === "IDSBRBBottleCurrent"
                        || columnName === "IDSBBRBottlePlan" || columnName === "IDSBBRBottleCurrent");
                },
                init: function () {
                    this.callParent(arguments);
                    this.set("IsPageable", false);
                    this.set("RowCount", 28000);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },
                onReloadRefrigeratorsInTMAGrid: function (args) {
                    var id = this.get("MasterRecordId");
                    debugger;
                    if (id === args) {
                        this.reloadGridData();
                    }
                },
                addGridDataColumns: function (esq) {
                    this.callParent(arguments);
                    if (!esq.columns.contains("IDSBParent")) {
                        esq.addColumn("IDSBParent");
                    }
                },
                getGridDataColumns: function () {
                    var gridDataColumns = this.callParent(arguments);
                    if (!gridDataColumns.IDSBParent) {
                        gridDataColumns.IDSBParent = {
                            path: "IDSBParent"
                        };
                    }
                    return gridDataColumns;
                },
                addToolsButtonMenuItems: function (toolsButtonMenu) {
                    this.addGridOperationsMenuItems(toolsButtonMenu);
                    if (this.useDetailWizard) {
                        this.addDetailWizardMenuItems(toolsButtonMenu);
                    }
                },
                prepareResponseCollection: function (collection) {
                    collection.each(function (item) {
                        var parent = item.get("IDSBParent");
                        var parentId = parent && parent.value;
                        if (parentId) {
                            item.set("IDSBParentId", parentId);
                        }
                        Terrasoft.each(item.columns, function (column) {
                            this.addColumnLink(item, column);
                            this.applyColumnDefaults(column);
                        }, this);
                    }, this);
                }
            }
        };
    });

Изображение удалено.

Нравится

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

Навряд ли кто то взглянув на не один десяток строк кода ответит вам почему возникает проблема при сохранении (скорее всего редактируемость и иерархичность не совместимы).

В любом случае вам может помочь только отладка кода!

решил задачу тупо влоб, переопределив метод сохранения. Написал своё сохранение, вызывая сервис из сервера. немного медленно, но работает

saveRowChanges: function (row, callback, scope) {
                    scope = scope || this;
                    callback = callback || Terrasoft.emptyFn;
                    if (row && this.getIsRowChanged(row)) {
                        if (row.values.IDSBParent !== "") {
                            this.saveChildRow(row, callback, scope);
                        }
                        else {
                            this.saveParentRow(rowm, callback, scope);
                        }
                    } else {
                        callback.call(scope);
                    }
                },
saveChildRow: function (row, callback, scope) {
                    var changed = row.changedValues;
                    debugger;
                    if (!changed.hasOwnProperty("IDSBBRBottleCurrent")) {
                        changed.IDSBBRBottleCurrent = row.values.IDSBBRBottleCurrent;
                    }
                    if (!changed.hasOwnProperty("IDSBBRBottlePlan")) {
                        changed.IDSBBRBottlePlan = row.values.IDSBBRBottlePlan;
                    }
                    if (!changed.hasOwnProperty("IDSBRBBottlePlan")) {
                        changed.IDSBRBBottlePlan = row.values.IDSBRBBottlePlan;
                    }
                    if (!changed.hasOwnProperty("IDSBRBBottleCurrent")) {
                        changed.IDSBRBBottleCurrent = row.values.IDSBRBBottleCurrent;
                    }
                    callback = this.reloadGridData;
                    var serviceSaveData = {
                        RowId: row.values.Id,
                        bottles: changed
                    }
                    ServiceHelper.callService("IDSBPlacingREService", "SaveChildRow",
                        callback, serviceSaveData, scope);
                }

 

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

Создал иерархическую деталь с редактируемым реестром. Но появилась проблема при количестве дочерних элементов больше 8. Они почему не отображаются, выдается ошибка Cannot read property 'getAttribute' of null. В БД всё верно. 

Вот код детали

define("IDSBRefrigeratorInTMADetail",
    ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"],
    function () {
        return {
            messages: {
                "ReloadRefrigeratorsInTMAGrid": {
                    "mode": Terrasoft.MessageMode.BROADCAST,
                    "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
                }
            },
            entitySchemaName: "IDSBRefrigeratorInTMA",
            attributes: {
                "IsEditable": {
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: true
                }
            },
            mixins: {
                ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
            },
            details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "DataGrid",
                    "values": {
                        "hierarchical": true,
                        "hierarchicalColumnName": "IDSBParent",
                        "maxColumns": 48,
                        "maxRowsCount": 10000,
                        "className": "Terrasoft.ConfigurationGrid",
                        "generator": "ConfigurationGridGenerator.generatePartial",
                        "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
                        "changeRow": { "bindTo": "changeRow" },
                        "unSelectRow": { "bindTo": "unSelectRow" },
                        "onGridClick": { "bindTo": "onGridClick" },
                        "activeRowAction": { "bindTo": "onActiveRowAction" },
                        "initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
                        "multiSelect": false
                    }
                },
                {
                    "operation": "remove",
                    "name": "AddRecordButton"
                }]/**SCHEMA_DIFF*/,
            methods: {
                generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {
                    this.columnsConfig = columnsConfig;
                    var gridData = this.getGridData();
                    var activeRow = gridData.get(id);
                    var isEditableColumn;
                    if (activeRow.values.IDSBParent === "") {
                        isEditableColumn = this.isEditableParentColumn;
                    }
                    else {
                        isEditableColumn = this.isEditableColumn;
                    }
                    var gridLayoutItems = [];
                    var currentColumnIndex = 0;
                    Terrasoft.each(columnsConfig, function (columnConfig) {
                        var cellConfig = this.getActiveRowCellConfig(columnConfig, currentColumnIndex);
                        cellConfig.enabled = isEditableColumn(cellConfig.name);
                        if (!cellConfig.hasOwnProperty("isNotFound")) {
                            gridLayoutItems.push(cellConfig);
                        }
                        currentColumnIndex += cellConfig.layout.colSpan;
                    }, this);
                    this.applyBusinessRulesForActiveRow(id, gridLayoutItems);
                    var viewGenerator = Ext.create(this.getRowViewGeneratorClassName());
                    viewGenerator.viewModelClass = this;
                    var gridLayoutConfig = viewGenerator.generateGridLayout({
                        name: this.name,
                        items: gridLayoutItems
                    });
                    rowConfig.push(gridLayoutConfig);
                },
                isEditableParentColumn: function (columnName) {
                    return false;
                },
                isEditableColumn: function (columnName) {
                    return (columnName === "IDSBBottlePlan");
                }/*,
                init: function () {
                    this.callParent(arguments);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },
                onReloadRefrigeratorsInTMAGrid: function (args) {
                    this.reloadGridData();
                }*/
            }
	};
});

 

Нравится

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

Для упрощения отладки посмотрите SQL профайлером запросы которые отправляются в БД.

Григорий Чех, думаете нужно заместить метод addGridDataColumns?

Григорий имел в виду использование профайлера. Естественно, только для случаев, когда есть доступ к серверу БД.

посмотрел профайлер. Выполняется следующий запрос. Забил его сам в SQL Management. Выдал недостающие элементы, которые как раз невыведены на экран. Ошибка возникает когда нажимаю "Показать больше"

SELECT
	[IDSBRefrigeratorInTMA].[Id] [Id],
	[IDSBRefrigeratorInTMA].[IDSBStreet] [IDSBStreet],
	[IDSBRefrigeratorInTMA].[IDSBCustomerInTMAId] [IDSBCustomerInTMAId],
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] [ITTradeMarketId],
	[ITTradeMarket].[ITName] [ITTradeMarket.ITName],
	[IDSBRefrigeratorInTMA].[MonthId] [MonthId],
	[Month].[Name] [Month.Name],
	[IDSBRefrigeratorInTMA].[IDSBBottlePlan] [IDSBBottlePlan],
	[IDSBRefrigeratorInTMA].[IDSBParentId] [IDSBParentId],
	[IDSBParent].[IDSBStreet] [IDSBParent.IDSBStreet],
	[ITTradeMarket].[ITTypeId] [ITTradeMarket.ITTypeId],
	[ITType].[Name] [ITType.Name],
	(
SELECT
	COUNT([SubEntryPoint].[Id]) [Count]
FROM
	[dbo].[EntryPoint] [SubEntryPoint] WITH(NOLOCK)
WHERE
	[SubEntryPoint].[EntityId] = [IDSBRefrigeratorInTMA].[Id]
	AND [SubEntryPoint].[IsActive] = 1) [SubEntryPoint],
	[IDSBRefrigeratorInTMA].[CreatedOn] [CreatedOn],
	[IDSBRefrigeratorInTMA].[CreatedById] [CreatedById],
	[CreatedBy].[Name] [CreatedBy.Name],
	[CreatedBy].[PhotoId] [CreatedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ModifiedOn] [ModifiedOn],
	[IDSBRefrigeratorInTMA].[ModifiedById] [ModifiedById],
	[ModifiedBy].[Name] [ModifiedBy.Name],
	[ModifiedBy].[PhotoId] [ModifiedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ProcessListeners] [ProcessListeners]
FROM
	[dbo].[IDSBRefrigeratorInTMA] [IDSBRefrigeratorInTMA] WITH(NOLOCK)
	LEFT OUTER JOIN [dbo].[ITTradeMarket] [ITTradeMarket] WITH(NOLOCK) ON ([ITTradeMarket].[Id] = [IDSBRefrigeratorInTMA].[ITTradeMarketId])
	LEFT OUTER JOIN [dbo].[Month] [Month] WITH(NOLOCK) ON ([Month].[Id] = [IDSBRefrigeratorInTMA].[MonthId])
	LEFT OUTER JOIN [dbo].[IDSBRefrigeratorInTMA] [IDSBParent] WITH(NOLOCK) ON ([IDSBParent].[Id] = [IDSBRefrigeratorInTMA].[IDSBParentId])
	LEFT OUTER JOIN [dbo].[ITITTradeMarketType1] [ITType] WITH(NOLOCK) ON ([ITType].[Id] = [ITTradeMarket].[ITTypeId])
	LEFT OUTER JOIN [dbo].[Contact] [CreatedBy] WITH(NOLOCK) ON ([CreatedBy].[Id] = [IDSBRefrigeratorInTMA].[CreatedById])
	LEFT OUTER JOIN [dbo].[Contact] [ModifiedBy] WITH(NOLOCK) ON ([ModifiedBy].[Id] = [IDSBRefrigeratorInTMA].[ModifiedById])
WHERE
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] = '54368FDE-6D00-4BDE-BAAE-EDEA56EBAA33'
ORDER BY
	[Id] ASC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

 

Может, 8 элементов видно как раз из-за выборки порциями по 10? Судя по окончанию SQL-запроса, это как раз вторая десятка, первая пропущена.

А где именно вылетает «Cannot read property 'getAttribute' of null», полный стек не видно?

Вылетает на этом методе. В строке var n = this.getDomRow(i) в n кладется undefined и далее соответственно вылетает ошибка. В i в этот момент родительская колонка

onCollectionDataLoaded: function(e, t, a) {
        if (this.theoreticallyActiveRows = null,
        !this.rows.length)
            return this.collection = this.collection || e,
            this.prepareCollectionData(),
            void this.safeRerender();
        if (!Ext.Object.isEmpty(t) && this.rendered) {
            var r = []
              , s = {
                rows: r
            };
            if (t.each(function(e) {
                this.prepareCollectionItem(e);
                var t = this.getRow(e);
                r.push(t),
                a && ("top" !== a.mode ? this.rows.push(t) : this.rows.splice(0, 0, t))
            }, this),
            this.hierarchical && !t.isEmpty()) {
                var i = t.getByIndex(0).get(this.hierarchicalColumnName);
                if (s[this.hierarchicalColumnName] = i,
                "listed" === this.type && i) {
                    var n = this.getDomRow(i)
                      , o = parseInt(n.getAttribute("level"), 10);
                    s.rowLevel = o + 1
                }
            }
            var l = [];
            this.renderGrid(l, s);
            for (var c = "", h = 0, u = l.length; h < u; h += 1)
                c += Ext.DomHelper.createHtml(l[h]);
            Ext.Object.isEmpty(a) && (a = {
                mode: "bottom"
            }),
            this.addRows(c, a),
            this.checkNeedLoadData()
        }
    },

 

Что-то не могу найти такой функции в «коробке».

А иерархичность и редактируемость сами по себе совместимы? На других таких деталях ограничения в 8 нет?

Если убираю редактируемость, ошибка не исчезает. Если убираю иерархичность, всё отображается нормально

Это логично, если сбой при превышении 8 потомков. В плоской детали никаких потомков нет. Сравните с другими иерархическими деталями, есть там такое ограничение или нет?

Решил проблему. Добавил значения атрибутов, чтобы всё грузилось сразу. В моем случае такое решение вполне подходит

init: function () {
                    this.callParent(arguments);
                    this.set("IsPageable", false);
                    this.set("RowCount", 28000);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },

 

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

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