Как программно заполнить список выбора для колонки табличной части в управляемых формах 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Архитектурная особенность управляемых форм

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

Отсюда вытекают две критически важные проблемы:

  1. Выбор неподходящего события формы: попытка заполнять список в событии ПриАктивизацииСтроки приводит к постоянным вызовам сервера при каждом перемещении курсора по строкам таблицы, что вызывает заметные зависания интерфейса.
  2. Отображение значений: если для поля колонки включено свойство РежимВыбораИзСписка = Истина, платформа пытается сопоставить текущее значение ячейки со значениями из списка выбора. Если список динамически перезаписан для другой строки, в остальных строках вместо представлений могут отображаться пустые ячейки или сырые идентификаторы.

Подготовка элемента управления в конфигураторе

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

  1. Установим свойство КнопкаСпискаВыбора в значение Истина (или Да). Это обеспечит отображение стрелки выпадающего списка в ячейке.
  2. Свойство РежимВыбораИзСписка рекомендуется оставить в значении Ложь, если состав списков между строками различается. Это гарантирует корректную отрисовку ранее введенных данных в других строках.

Решение 1: Использование события НачалоВыбораИзСписка

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

Рассмотрим по шагам реализацию данного обработчика на клиенте и получение данных на сервере:


&НаСервереБезКонтекста
Функция ПолучитьСписокВыбораДляСтроки(ЗначениеУсловия)
    
    Список = Новый СписокЗначений;
    
    // Здесь выполняем запрос к базе данных с учетом переданного условия
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    СправочникНоменклатура.Ссылка КАК Значение,
        |    СправочникНоменклатура.Наименование КАК Представление
        |ИЗ
        |    Справочник.Номенклатура КАК СправочникНоменклатура
        |ГДЕ
        |    СправочникНоменклатура.Родитель = &Родитель";
        
    Запрос.УстановитьПараметр("Родитель", ЗначениеУсловия);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        Список.Добавить(Выборка.Значение, Выборка.Представление);
    КонецЦикла;
    
    Возврат Список;
    
КонецФункции

&НаКлиенте
Процедура ТоварыКолонкаЗначениеНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
    
    // Получаем текущие данные строки
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Обязательно очищаем предыдущие значения списка, 
    // чтобы элементы не дублировались при повторном открытии
    Элемент.СписокВыбора.Очистить();
    
    // Получаем актуальный список для текущей строки
    СписокДанных = ПолучитьСписокВыбораДляСтроки(ТекущаяСтрока.Группа);
    
    // Заполняем список выбора элемента формы
    Для Каждого ЭлементСписка Из СписокДанных Цикл
        Элемент.СписокВыбора.Добавить(ЭлементСписка.Значение, ЭлементСписка.Представление);
    КонецЦикла;
    
КонецПроцедуры

Важно: вызов Элемент.СписокВыбора.Очистить() строго обязателен. Если его пропустить, при каждом повторном нажатии на кнопку выбора элементы будут дублироваться и список разрастется.

Решение 2: Асинхронный выпадающий список через ПоказатьВыборИзСписка

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

Разберем пример реализации:


&НаКлиенте
Процедура ТоварыКолонкаЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем список значений с сервера
    СписокДляВыбора = ПолучитьСписокВыбораДляСтроки(ТекущаяСтрока.Группа);
    
    // Настраиваем оповещение о завершении выбора
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораИзСписка", ЭтотОбъект);
    
    // Показываем меню, привязанное к текущему элементу формы
    ПоказатьВыборИзСписка(Оповещение, СписокДляВыбора, Элемент);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораИзСписка(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныйЭлемент = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока <> Неопределено Тогда
        ТекущаяСтрока.КолонкаЗначение = ВыбранныйЭлемент.Значение;
    КонецЕсли;
    
КонецПроцедуры

Этот способ более безопасен для интерфейса, так как свойство СписокВыбора самого элемента управления остается нетронутым.

Рекомендации по оптимизации и удобству работы

  1. Кэширование на клиенте: если в табличной части много строк и данные для списков повторяются (например, зависят от одной и той же категории товаров), кэшируйте полученные списки выбора в реквизите формы типа Соответствие. Это исключит повторные серверные вызовы при повторном клике.
  2. Типовой механизм «Связи параметров выбора»: если поле ссылается на объект базы данных (справочник, документ), проверьте возможность использования стандартного свойства поля СвязиПараметровВыбора без написания кода.
  3. Ввод текста с клавиатуры: обработчик НачалоВыбораИзСписка срабатывает только при клике мышью по кнопке раскрывающегося списка. Если пользователю требуется вводить текст вручную с автоподбором вариантов, дополнительно переопределите обработчики события АвтоПодбор и ОкончаниеВводаТекста у того же поля ввода.
← На главную