При разработке интерфейсов на управляемых формах часто возникает задача связать две таблицы. Например, когда пользователь выбирает строку в иерархическом дереве заявок, во второй таблице (корзине товаров) должны отобразиться только те строки, которые соответствуют выбранному узлу. Рассмотрим подробнее, как реализовать такой механизм без ошибок и проанализируем частые «глюки», с которыми сталкиваются программисты.
Представим ситуацию: на форме есть дерево значений ДеревоЗаявок и таблица КорзинаВыдаваемыхТМЦ. Мы хотим обновлять отбор во второй таблице в событии ПриАктивизацииСтроки первого дерева. Зачастую разработчики пытаются конструировать объект ФиксированнаяСтруктура «на лету», передавая в конструктор строку с именами свойств и сами значения.
Посмотрим на ошибочный вариант реализации, который может приводить к неожиданным результатам при отладке:
&НаКлиенте
Процедура ДеревоЗаявокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.ДеревоЗаявок.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Если ТекущиеДанные.НомерЗаявки <> "" Тогда
ОтборПоКорзинe = Новый ФиксированнаяСтруктура("НомерЗаявки", ТекущиеДанные.НомерЗаявки);
Если НЕ ТекущиеДанные.ТМЦ.Пустая() Тогда
ОтборПоКорзинe = Новый ФиксированнаяСтруктура("НомерЗаявки,ТМЦ", ТекущиеДанные.НомерЗаявки, ТекущиеДанные.ТМЦ);
Если НЕ ТекущиеДанные.ФизЛицо.Пустая() Тогда
ОтборПоКорзинe = Новый ФиксированнаяСтруктура("НомерЗаявки,ТМЦ,ФизЛицо", ТекущиеДанные.НомерЗаявки, ТекущиеДанные.ТМЦ, ТекущиеДанные.ФизЛицо);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Элементы.КорзинаВыдаваемыхТМЦ.ОтборСтрок = ОтборПоКорзинe;
КонецПроцедуры
В этом коде кроется серьезный недостаток: логика формирования отбора жестко завязана на вложенность условий. Если, например, НомерЗаявки окажется пустой строкой, то структура отбора вообще не сформируется, даже если ФизЛицо или ТМЦ заполнены. Из-за этого может казаться, что платформа отрабатывает условие с ошибкой.
Чтобы избежать подобных логических ловушек, выясним причину и применим более гибкий подход. Свойство ОтборСтрок таблицы формы принимает готовый объект ФиксированнаяСтруктура. Лучше всего сначала создать обычный объект Структура, наполнить его нужными параметрами в независимых условиях, а в самом конце передать эту структуру в конструктор фиксированной структуры.
Разберем по шагам рабочий и надежный вариант кода:
&НаКлиенте
Процедура ДеревоЗаявокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.ДеревоЗаявок.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Элементы.КорзинаВыдаваемыхТМЦ.ОтборСтрок = Неопределено;
Возврат;
КонецЕсли;
СтруктураПараметров = Новый Структура;
Если ЗначениеЗаполнено(ТекущиеДанные.НомерЗаявки) Тогда
СтруктураПараметров.Вставить("НомерЗаявки", ТекущиеДанные.НомерЗаявки);
КонецЕсли;
Если ЗначениеЗаполнено(ТекущиеДанные.ТМЦ) Тогда
СтруктураПараметров.Вставить("ТМЦ", ТекущиеДанные.ТМЦ);
КонецЕсли;
Если ЗначениеЗаполнено(ТекущиеДанные.ФизЛицо) Тогда
СтруктураПараметров.Вставить("ФизЛицо", ТекущиеДанные.ФизЛицо);
КонецЕсли;
Если СтруктураПараметров.Количество() > 0 Тогда
Элементы.КорзинаВыдаваемыхТМЦ.ОтборСтрок = Новый ФиксированнаяСтруктура(СтруктураПараметров);
Иначе
Элементы.КорзинаВыдаваемыхТМЦ.ОтборСтрок = Неопределено;
КонецЕсли;
КонецПроцедуры
Проанализируем дополнительные особенности, которые нужно учитывать при работе со свойством ОтборСтрок и объектом ДанныеФормыДерево:
ЗначениеЗаполнено() вместо Пустая(). Если в дереве используются разные уровни группировок, на одном из уровней колонка ссылочного типа может содержать Неопределено или Null. Вызов Пустая() у таких типов приведет к ошибке выполнения скрипта на клиенте. Метод ЗначениеЗаполнено() безопасен для любых типов данных.ПолучитьРодителя() у объекта ДанныеФормыЭлементДерева в цикле до достижения корня.ОтборСтрок поддерживает только точное совпадение по условию «И». Если вы передадите в структуру несколько ключей, платформа будет искать строки, где совпадают все указанные значения. Использование сложных условий (например, «ИЛИ» или сравнений «Больше/Меньше») в данном случае невозможно.Неопределено. Если вы передадите структуру с пустыми значениями, платформа попытается найти строки, где реквизиты буквально равны пустым ссылкам или пустым строкам.Событие ПриАктивизацииСтроки вызывается очень часто: при навигации стрелками клавиатуры, при открытии формы и перерисовках. Если подчиненная таблица содержит тысячи строк, клиентская фильтрация с помощью ОтборСтрок может вызывать подтормаживание интерфейса.
Рассмотрим, как можно оптимизировать этот процесс:
ПодключитьОбработчикОжидания() с задержкой, например, 0.1 или 0.2 секунды.Используя правильный подход к формированию структуры через метод Вставить(), вы сделаете ваш код надежным, легко читаемым и защищенным от логических ошибок при неполном заполнении данных в дереве.