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