Как в управляемой форме отложить действие до показа диалога

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

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

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

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

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

Я расширял процедуру СтартоватьИЗакрыть модуля КомандыРаботыСБизнесПроцессамиКлиент:

&Вместо("СтартоватьИЗакрыть")
Процедура дор_СтартоватьИЗакрыть(Форма)
	//Осипов 2021-09-01
	...
	//Определяем внутренний документ
	ВнутреннийДокумент = дор_Сервер.ОсновнойВнутреннийДокументБизнесПроцесса(Форма.Объект); 
	Если НЕ ЗначениеЗаполнено(ВнутреннийДокумент) Тогда
		Перейти ~Стандартно;
	КонецЕсли;

	
	//Открываем форму выбора подразделений
	ПараметрыФормы = Новый Структура();
	ПараметрыФормы.Вставить("ВнутреннийДокумент", ВнутреннийДокумент); 
	
	ДополнительныеПараметры = Новый Структура(); //При закрытии формы отработают
	ДополнительныеПараметры.Вставить("Форма", Форма); 
	ДополнительныеПараметры.Вставить("ВнутреннийДокумент", ВнутреннийДокумент); 
	
	ОписаниеОповещенияОЗакрытии = Новый ОписаниеОповещения("дор_ПослеВыбораПодразделенийДляГрупповогоСогласования", КомандыРаботыСБизнесПроцессамиКлиент, ДополнительныеПараметры);
	ОткрытьФорму("...Форма.ВыборПодразделенийДляГрупповогоСогласования", ПараметрыФормы, ,,,,ОписаниеОповещенияОЗакрытии, РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс);
	Возврат; //Предыдущий обработчик не вызываем
	
	~Стандартно:
	ПродолжитьВызов(Форма);
КонецПроцедуры

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

Как видно из кода, я не делаю вызов стандартной процедуры, делая возврат из процедуры после показа формы ввода дополнительных данных, перед ПродолжитьВызов.

Кстати, при описании обработчика оповещения в коде вместо названия модуля можно использовать ЭтотОбъект, я об этом знал, но сразу не получилось почему-то, поэтому в коде осталось имя модуля.

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

Сначала я попробовал добавить процедуре необязательный параметр:

&Вместо("СтартоватьИЗакрыть")
Процедура дор_СтартоватьИЗакрыть(Форма, ВыполнятьСтандартноСразу = ложь)

Но так 1С не восприняла расширение процедуры и моя процедура просто не вызвалась, т.к. у нее был «лишний» параметр, хотя и не обязательный.

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

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

Эти попытки заняли минут 40.

Я уже было хотел где-то в клиентском кэше хранить, какие формы у меня надо предварять вводом дополнительных данных, какие нет, т.е. хранить список форм.

Но, к счастью, не стал этим заниматься, а выкрутился по-простому:

&Вместо("СтартоватьИЗакрыть")
Процедура дор_СтартоватьИЗакрыть(Форма)
	...
	Если ТипЗнч(Форма) = Тип("Структура") Тогда
		Форма = Форма.Форма;
		Перейти ~Стандартно;
	КонецЕсли;
	...
	
	~Стандартно:
	ПродолжитьВызов(Форма);
КонецПроцедуры

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

Я обернул форму в структуру и на входе смотрел — если это форма, значит первый вызов и надо показывать дополнительную форму, а если на входе структура — надо вызывать стандартный обработчик.

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

Единственно, хочу заметить, что я пытался еще вызвать процедуру расширения напрямую:

дор_СтартоватьИЗакрыть(Новый Структура("Форма", ДополнительныеПараметры.Форма));

Но 1С так не смогла, она вызвала процедуру, но ругнулась на «ПродолжитьВызов», потому что не «знала», кто вызвал эту функцию.

Вот код, где я пытался добавлять реквизиты и элементы на форме, выкладываю, может пригодится кому:

//МОДУЛЬ дор_КлиентСервер: (клиент-серверный)
#Область СлужебныйРеквизит
Функция ПолучитьСлужебныйРеквизитФормы(Знач Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    ГарантироватьСлужебныйРеквизитФормы(Форма, Имя);
    Возврат Форма[Имя];
КонецФункции

Функция УстановитьСлужебныйРеквизитФормы(Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64", Значение) Экспорт
    ГарантироватьСлужебныйРеквизитФормы(Форма, Имя);
    Форма[Имя] = Значение;
КонецФункции

Функция ЕстьСлужебныйРеквизитФормы(Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    //Отсюда: https://forum.mista.ru/topic.php?id=844075
    ТестЗначение = "52627514-b2e3-48a7-853f-f8047ade8f4c";
    Структура = Новый Структура(Имя, ТестЗначение);
    ЗаполнитьЗначенияСвойств(Структура, Форма);
    Возврат Структура[Имя] <> ТестЗначение;
    //МассивРеквизитов = дор_Сервер.ПолучитьРеквизитыФормы(Форма);
    //Для каждого ТекРеквизит Из МассивРеквизитов Цикл
    //    Если ТекРеквизит.Имя = Имя Тогда
    //        Возврат Истина;
    //    КонецЕсли;
    //КонецЦикла;    
    //Возврат ложь;
КонецФункции

Процедура ГарантироватьСлужебныйРеквизитФормы(Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    
    Если ЕстьСлужебныйРеквизитФормы(Форма, Имя) Тогда
        Возврат;
    КонецЕсли;
    
    дор_Сервер.ДобавитьРеквизитФормы(Форма, Имя, Новый ОписаниеТипов());
    

КонецПроцедуры

#КонецОбласти

#Область СлужебныйФлаг
Функция ПолучитьСлужебныйФлагФормы(Знач Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    ГарантироватьСлужебныйФлагФормы(Форма, Имя);
    Возврат Форма.Элементы[Имя].Подсказка <> "";
КонецФункции

Функция УстановитьСлужебныйФлагФормы(Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    ГарантироватьСлужебныйФлагФормы(Форма, Имя);
    Форма.Элементы[Имя].Подсказка = "!";
КонецФункции

Функция ЕстьСлужебныйФлагФормы(Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    Возврат Форма.Элементы.Найти(Имя) <> Неопределено;
КонецФункции

Процедура ГарантироватьСлужебныйФлагФормы(Форма, Имя = "_532a922e5b11450f96ac6e6b71ea0a64") Экспорт
    
    Если ЕстьСлужебныйФлагФормы(Форма, Имя) Тогда
        Возврат;
    КонецЕсли;
    
    //Добавляем невидимый элемент
    ТекЭлемент = Форма.Элементы.Добавить(Имя, Тип("ПолеФормы"));
    ТекЭлемент.Видимость = ложь;

КонецПроцедуры

#КонецОбласти


//МОДУЛЬ дор_Сервер: (серверный)

Функция ПолучитьРеквизитыФормы(Знач Форма) Экспорт
    Возврат Форма.ПолучитьРеквизиты();
КонецФункции

Процедура ДобавитьРеквизитФормы(Форма, Имя, Тип) Экспорт
    
    ДобавляемыеРеквизиты = Новый Массив();
    ТекРеквизит = Новый РеквизитФормы(Имя, Тип);
    ДобавляемыеРеквизиты.Добавить(ТекРеквизит);

    Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);     
    
КонецПроцедуры

Мне в этом коде нравится, как я на клиенте, не обращаясь на сервер через заполнение значение свойств проверяю наличие реквизита у формы. Кстати, я использую GUID для генерации уникального названия реквизита или поля формы.

Но код оказался бесполезен, он работает только на сервере.

Среда: Документооборот 8 КОРП 2.1.26.2 Объем факт: 2 час.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

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

  1. Павел:

    Вот п.э. с 1с все и сваливают у кого мозг отрастает — задалбывает дрочево и бесконечное строительство костылей псли хотелка в типовую не вписывается

Добавить комментарий

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