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

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

При разработке документов в 1С часто возникает задача: если реквизит шапки (например, Контрагент или Договор) изменяется, требуется перезаполнить или очистить подчиненную табличную часть. При этом необходимо спросить у пользователя подтверждение. Если пользователь отказывается от очистки, изменение реквизита должно быть отменено, а старое значение — восстановлено.

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

Разберем причины такого поведения платформы и рассмотрим проверенный стандартный паттерн решения этой задачи.

Почему не удается заблокировать выбор через НачалоВыбора

Проанализируем особенности работы клиентских событий в управляемом интерфейсе:

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

Общепринятый паттерн решения: откат значения в ПриИзменении

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

Шаг 1. Создание реквизита для хранения предыдущего значения

Добавим в форму вспомогательный реквизит, например КонтрагентПредыдущееЗначение (тип совпадает с типом реквизита Объект.Контрагент).

Шаг 2. Инициализация предыдущего значения

При создании или чтении формы на сервере запоминаем текущее значение реквизита:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    КонтрагентПредыдущееЗначение = Объект.Контрагент;
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    КонтрагентПредыдущееЗначение = Объект.Контрагент;
КонецПроцедуры

Шаг 3. Обработка события ПриИзменении с асинхронным вопросом

В клиентском обработчике ПриИзменении проверяем, действительно ли значение изменилось и заполнена ли табличная часть. Если табличная часть содержит строки, задаем вопрос пользователю через ПоказатьВопрос с использованием ОписаниеОповещения.


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

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

Обработка события очистки поля

Пользователь может очистить поле ввода с помощью стандартной кнопки «крестик» (кнопка очистки). Для корректной обработки этого действия рекомендуется использовать событие элемента формы Очистка:


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

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

Дополнительные настройки элемента формы

Чтобы управлять поведением выпадающих списков и подсказок в поле ввода, полезно настроить свойства элемента управления в палитре свойств:

  1. История выбора при вводе (ИсторияВыбораПриВводе): Установка свойства в значение Не использовать отключает показ ранее выбранных значений при клике на поле.
  2. Быстрый выбор (БыстрыйВыбор): Если для реквизита установлено значение Ложь, платформа не будет пытаться открывать выпадающий список, а сразу откроет стандартную форму выбора из справочника.
  3. Автовыбор незаполненного (АвтоВыборНезаполненного): Отключение этой опции предотвращает автоматическое открытие окна выбора при переходе к пустому полю.

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

← На главную