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