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

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

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

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

Особенности асинхронной модели в событии таблицы

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

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

Также проанализируем вариант «дать строке добавиться, а при отрицательном ответе удалить её». Такой подход порождает множество скрытых проблем:

  1. Установка флага Модифицированность = Истина для формы сразу при создании строки.
  2. Срабатывание сопутствующих обработчиков событий (ПриНачалеРедактирования, автопересчет итогов и серверные вызовы).
  3. Нарушение нумерации строк и оставшийся признак модифицированности даже после последующего удаления.

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

Решение 1. Отмена стандартного добавления и вызов диалога с флагом-блокировкой

Рассмотрим подробнее реализацию через событие ПередНачаломДобавления. Если в обработчике ответа пользователя мы снова вызовем интерактивное добавление методом Элементы.ИмяТаблицы.ДобавитьСтроку(), платформа повторно вызовет событие ПередНачаломДобавления. Чтобы избежать бесконечной рекурсии, применим переменную контекста формы в качестве управляющего флага.

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


&НаКлиенте
Перем РазрешеноДобавлениеБезВопроса;

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

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

Разберем логику работы данного кода:

  1. При нажатии пользователем кнопки добавления срабатывает событие ПередНачаломДобавления.
  2. Флаг РазрешеноДобавлениеБезВопроса равен Ложь (или Неопределено), поэтому выставляется Отказ = Истина, стандартное создание строки прерывается, и открывается немодальное окно вопроса.
  3. Диалог блокирует интерфейс родительской формы, предотвращая нежелательные действия пользователя.
  4. Если пользователь нажимает «Да», взводится флаг РазрешеноДобавлениеБезВопроса = Истина и вызывается Элементы.Товары.ДобавитьСтроку().
  5. Событие срабатывает повторно, проверяет флаг, сбрасывает его в Ложь и дает строке штатно создаться с активацией фокуса на первой ячейке.

Решение 2. Программное добавление в коллекцию и активация строки

Выясним причину, почему разработчики иногда предпочитают добавлять строку не методом элемента формы ДобавитьСтроку(), а напрямую в данные объекта. Это удобно, если при создании требуется сразу заполнить реквизиты строки по умолчанию на клиенте или сервере.

При программном добавлении в коллекцию Объект.Товары.Добавить() строка не переходит в режим редактирования автоматически. Чтобы передать на неё фокус и открыть ввод данных, используем свойства ТекущаяСтрока и метод ИзменитьСтроку().

Посмотрим на пример кода:


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

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

Важный нюанс: при программном добавлении строки в Объект.Товары событие ПередНачаломДобавления повторно не вызывается, поэтому использование переменной-флага в данном сценарии не требуется.

Решение 3. Переопределение стандартной команды добавления

Еще один практический подход заключается в замене стандартного действия командной панели таблицы:

  1. Отключите видимость стандартной кнопки добавления на панели таблицы.
  2. Создайте собственную команду формы (например, ДобавитьТоварСВопросом) и вынесите её в командную панель.
  3. В действии команды вызовите диалог вопроса, а в оповещении выполните Элементы.Товары.ДобавитьСтроку().

Обратите внимание: если таблица формы позволяет добавлять строки горячей клавишей Insert или через контекстное меню, переопределения только кнопки на панели недостаточно — потребуется либо полностью отключить добавление в свойствах таблицы, либо комбинировать данный способ с перехватом события ПередНачаломДобавления.

← На главную