Почему не работает проверка заполнения реквизита Родитель в управляемой форме 1С

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

При разработке логики управляемых форм часто возникает задача сделать заполнение определенного реквизита обязательным только при наступлении определенных условий (например, в зависимости от выбранного пользователем режима работы, вида операции или варианта создания элемента). Разработчики нередко пытаются переопределить состав проверяемых полей прямо в обработчике формы ОбработкаПроверкиЗаполненияНаСервере, добавляя имя реквизита объекта в массив ПроверяемыеРеквизиты. Однако платформа пропускает такую валидацию и успешно записывает элемент с пустым значением.

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

Анализ проблемы: почему добавление реквизита в массив на форме не дает результата

Рассмотрим исходную ситуацию на примере типового фрагмента кода, в котором разработчик пытается проверить заполнение реквизита Родитель в иерархическом справочнике:


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

При отладке видно, что условие срабатывает и строка "Родитель" действительно помещается в массив ПроверяемыеРеквизиты. Но платформа не выдает ошибку и объект записывается пустым. Выясним причину этого явления:

  1. Разделение контекстов формы и объекта: событие управляемой формы ОбработкаПроверкиЗаполненияНаСервере предназначено исключительно для валидации собственных реквизитов формы. В переданном массиве ПроверяемыеРеквизиты содержатся только имена собственных реквизитов формы и имя основного реквизита (как правило, "Объект").
  2. Механизм обхода: платформа 1С не выполняет автоматический поиск реквизитов прикладного объекта внутри формы по их простым именам. Попытка добавить туда строку "Родитель" ни к чему не приводит, так как у самой формы нет такого реквизита верхнего уровня — он принадлежит объекту БД (Объект.Родитель).
  3. Где живет логика объекта: проверка стандартных и пользовательских реквизитов самого справочника или документа выполняется платформой в модуле объекта — внутри процедуры ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты).

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

Решение 1. Программная проверка в модуле формы с выводом понятного сообщения

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

Разберем по шагам правильную реализацию с использованием объекта СообщениеПользователю:


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

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

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

Решение 2. Стандартный подход 1С: проверка в модуле объекта «от обратного»

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

  1. В конфигураторе открываем свойства стандартного реквизита Родитель (или соответствующего реквизита объекта) и устанавливаем свойство «Проверка заполнения» в значение «Выдавать ошибку».
  2. При открытии формы платформа автоматически сделает реквизит визуально обязательным (подчеркнет его красной пунктирной линией) и включит в стандартный массив проверки при записи.
  3. В модуле объекта переопределяем событие ОбработкаПроверкиЗаполнения, удаляя реквизит из проверки в тех случаях, когда его заполнять не требуется:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    // Проверяем условие, при котором родитель НЕ обязателен
    Если НЕ ТребуетсяЗаполнятьРодителя Тогда
        
        Позиция = ПроверяемыеРеквизиты.Найти("Родитель");
        Если Позиция <> Неопределено Тогда
            ПроверяемыеРеквизиты.Удалить(Позиция);
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

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

Управление визуальным отображением обязательности на клиенте

Чтобы интерфейс формы своевременно реагировал на изменение условий и пользователь сразу видел, обязательно ли поле к заполнению, рекомендуется динамически управлять визуальными свойствами элемента формы. Разберем пример установки отметки незаполненного в обработчике изменения варианта создания:


&НаКлиенте
Процедура ВариантСозданияПриИзменении(Элемент)
    ОбновитьОбязательностьПолей();
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьОбязательностьПолей()
    
    ПроверкаРодителя = (ВариантСоздания = 1);
    Элементы.Родитель.АвтоОтметкаНезаполненного = ПроверкаРодителя;
    
КонецПроцедуры

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

Важные ограничения и особенности событий

При выборе места валидации данных обратим внимание на важные архитектурные особенности:

  1. Интерактивность проверок на форме: любые проверки в событиях формы (ОбработкаПроверкиЗаполненияНаСервере, ПередЗаписью) не выполняются, если запись объекта инициирована программно методом СправочникОбъект.Записать(). Если отсутствие родителя критично для целостности информационной базы, проверку обязательно нужно дублировать в модуле объекта.
  2. Последовательность вызовов: при нажатии кнопки сохранения формы сначала отрабатывает ОбработкаПроверкиЗаполненияНаСервере формы, затем ОбработкаПроверкиЗаполнения объекта, и лишь затем вызывается обработчик ПередЗаписьюНаСервере. Учитывайте этот порядок при передаче параметров между контекстами.
← На главную