При разработке интерфейсов на управляемых формах часто возникает задача: открыть отдельную вспомогательную форму для выбора или настройки параметров, а затем вернуть заполненную структуру данных обратно в документ и поместить ее в строку табличной части. Начинающие разработчики нередко сталкиваются с ошибками при определении владельца формы и путают механизмы оповещения платформы. Разберем по шагам, почему возникает проблема и как правильно организовать передачу данных.
Рассмотрим распространенную ситуацию. Разработчик пытается открыть форму выбора направления и в качестве владельца формы передает результат метода Добавить() табличной части:
// Ошибочный вариант вызова:
ОткрытьФорму("Документ.Случай.Форма.ФормаВыбораНаправления", , Объект.Назначения.Добавить());
Затем в форме выбора формируется структура с данными и вызывается метод ОповеститьОВыборе:
Выбор = Новый Структура;
Выбор.Вставить("НазначенияВидОбследования", НазначенияВидОбследования);
Выбор.Вставить("НазначенияПрофильКойкиПриРеабилитации", НазначенияПрофильКойкиПриРеабилитации);
Выбор.Вставить("НазначенияПрофильМедицинскойПомощи", НазначенияПрофильМедицинскойПомощи);
Выбор.Вставить("НазначенияСпециальностьВрача", НазначенияСпециальностьВрача);
ОповеститьОВыборе(Выбор);
В такой схеме данные не попадают в строку документа. Выясним основные причины:
ОткрытьФорму может выступать только управляемая форма (ЭтотОбъект) или конкретный элемент формы (например, ТаблицаФормы или ПолеВвода). Строка табличной части имеет тип ДанныеФормыЭлементКоллекции и не может быть владельцем формы.ОповеститьОВыборе не рассылает широковещательное сообщение всем формам. Он закрывает форму выбора и вызывает специализированное событие ОбработкаВыбора строго у владельца формы. Если в вызывающей форме разработчик пытается поймать результат в процедуре ОбработкаОповещения, код не сработает (процедура ОбработкаОповещения вызывается только глобальным методом Оповестить).Разберем классический способ взаимодействия через форму-владельца. В этом случае владельцем передается сама исходная форма, а добавление и заполнение строки табличной части выполняется в обработчике выбора.
Шаг 1. Открытие формы выбора из формы документа
Передаем текущую форму в качестве владельца:
&НаКлиенте
Процедура КомандаДобавитьНазначение(Команда)
// Владельцем формы передаем саму форму документа (ЭтотОбъект)
ОткрытьФорму("Документ.Случай.Форма.ФормаВыбораНаправления", , ЭтотОбъект);
КонецПроцедуры
Шаг 2. Отправка результата из формы выбора
В форме выбора формируем структуру параметров и оповещаем владельца:
&НаКлиенте
Процедура ЗавершитьВыбор(Команда)
Выбор = Новый Структура;
Выбор.Вставить("ВидОбследования", НазначенияВидОбследования);
Выбор.Вставить("ПрофильКойкиПриРеабилитации", НазначенияПрофильКойкиПриРеабилитации);
Выбор.Вставить("ПрофильМедицинскойПомощи", НазначенияПрофильМедицинскойПомощи);
Выбор.Вставить("СпециальностьВрача", НазначенияСпециальностьВрача);
ОповеститьОВыборе(Выбор);
КонецПроцедуры
Шаг 3. Обработка выбранного значения в форме документа
В модуле формы документа создаем обработчик предопределенного события формы ОбработкаВыбора. Чтобы быстро перенести все поля из структуры в реквизиты строки, используем метод ЗаполнитьЗначенияСвойств:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
// Добавляем новую строку в табличную часть
НоваяСтрока = Объект.Назначения.Добавить();
// Быстро переносим совпавшие по именам реквизиты
ЗаполнитьЗначенияСвойств(НоваяСтрока, ВыбранноеЗначение);
КонецЕсли;
КонецПроцедуры
Если строку табличной части необходимо создать или определить заранее (до открытия окна), наиболее надежным и гибким решением платформы 1С 8.3 является использование объекта ОписаниеОповещения.
Посмотрим на пример реализации с передачей идентификатора созданной строки:
В вызывающей форме:
&НаКлиенте
Процедура ДобавитьИЗаполнитьНазначение(Команда)
// Добавляем строку и фиксируем ее уникальный идентификатор в данных формы
НоваяСтрока = Объект.Назначения.Добавить();
ИдентификаторСтроки = НоваяСтрока.ПолучитьИдентификатор();
// Создаем описание оповещения и передаем идентификатор в параметры
Оповещение = Новый ОписаниеОповещения("ПослеВыбораНаправления", ЭтотОбъект, ИдентификаторСтроки);
// Открываем форму с указанием обработчика закрытия
ОткрытьФорму("Документ.Случай.Форма.ФормаВыбораНаправления", , ЭтотОбъект, , , , Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораНаправления(РезультатВыбора, ИдентификаторСтроки) Экспорт
Если РезультатВыбора = Неопределено Тогда
// Пользователь просто закрыл окно без выбора - удаляем пустую строку
СтрокаДляУдаления = Объект.Назначения.НайтиПоИдентификатору(ИдентификаторСтроки);
Если СтрокаДляУдаления <> Неопределено Тогда
Объект.Назначения.Удалить(СтрокаДляУдаления);
КонецЕсли;
Возврат;
КонецЕсли;
// Находим созданную строку по идентификатору и заполняем ее
ТекущаяСтрока = Объект.Назначения.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ТекущаяСтрока <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(ТекущаяСтрока, РезультатВыбора);
КонецЕсли;
КонецПроцедуры
В форме выбора:
В этом случае при подтверждении ввода достаточно вызвать Закрыть(Выбор) или ОповеститьОВыборе(Выбор) — переданная структура автоматически поступит в первый параметр процедуры-обработчика РезультатВыбора.
Если форма выбора создается исключительно для того, чтобы запросить у пользователя заполнение только части колонок, проанализируем альтернативные варианты реализации:
ПриИзменении или событии таблицы ПриАктивизацииСтроки программно настраивается доступность нужных полей ввода через элементы формы (Элементы.НазначенияПрофильКойки.Доступность) или настраивается условное оформление.ПоказатьВводЗначения без проектирования отдельных экранных форм.