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