/form-patterns — паттерны компоновки форм
Справочник типовых паттернов дизайна управляемых форм 1С. Используй перед созданием формы через unica.apply с операциями form.create и element.add, когда требования пользователя не детализируют расположение элементов.
Как использовать: выбери подходящий архетип, применяй конвенции именования, сверяйся с UX-правилами для элементов, при необходимости используй продвинутые паттерны.
Архетипы форм
Форма документа
Шапка (horizontal, 2 колонки)
├─ Левая (vertical): НомерДата (H: Номер + Дата "от"), Контрагент, Договор
├─ Правая (vertical): Организация, Подразделение, ЦеныИВалюта (надпись-ссылка)
Страницы (pages)
├─ Товары: таблица Объект.Товары
├─ Услуги: таблица Объект.Услуги (опционально)
└─ Дополнительно: прочие реквизиты
Подвал (vertical)
├─ Итоги (horizontal): Всего, НДС, Скидка
└─ КомментарийОтветственный (horizontal): Комментарий + Ответственный
События: OnCreateAtServer, OnReadAtServer, OnOpen, BeforeWriteAtServer, AfterWriteAtServer, AfterWrite, NotificationProcessing Свойства: autoTitle=false
Форма обработки (DataProcessor)
Параметры (vertical)
├─ Группа полей ввода (Организация, Период, режимы работы)
├─ Информационные надписи (label, hyperlink)
Рабочая область
├─ Таблица данных или Pages с вкладками
Кнопки действий
├─ Выполнить / Применить (defaultButton)
├─ Закрыть (stdCommand: Close)
События: OnCreateAtServer, OnOpen, NotificationProcessing Свойства: windowOpeningMode=LockOwnerWindow (если диалог), autoTitle=false
Форма списка
Отборы (group: alwaysHorizontal)
├─ ГруппаОтбор[Поле] (H): Флажок + Поле ввода (для каждого фильтра)
Список (table, DynamicList)
├─ Колонки: labelField (не input — данные только для чтения)
События: OnCreateAtServer, OnOpen, NotificationProcessing, OnLoadDataFromSettingsAtServer
Свойства: autoSaveDataInSettings=Use
Фильтры: пара реквизитов на каждый — Отбор[Поле] (значение) + Отбор[Поле]Использование (boolean)
Форма элемента справочника
Простая:
ГруппаРеквизитов (horizontal)
├─ Наименование -> Объект.Description
└─ Код -> Объект.Code (если нужен)
Сложная:
Главное (vertical)
├─ Наименование -> Объект.Description
├─ Параметры (horizontal, 2 колонки)
│ ├─ Левая: основные реквизиты
│ └─ Правая: дополнительные реквизиты
└─ КонтактныеДанные / Дополнительно (vertical)
События: OnCreateAtServer, OnReadAtServer, BeforeWriteAtServer, NotificationProcessing
Мастер (Wizard)
Страницы (pages, OnCurrentPageChange)
├─ Шаг1: описание + параметры
├─ Шаг2: основная работа
└─ Шаг3: результат
Кнопки (horizontal)
├─ Назад (command), Далее (command, defaultButton), Выполнить (command)
└─ Закрыть (stdCommand: Close)
Свойства: windowOpeningMode=LockOwnerWindow, commandBarLocation=None
Конвенции именования
Группы
| Назначение | Имя | Тип |
|---|---|---|
| Шапка | ГруппаШапка |
horizontal |
| Левая колонка | ГруппаШапкаЛевая |
vertical |
| Правая колонка | ГруппаШапкаПравая |
vertical |
| Номер+Дата | ГруппаНомерДата |
horizontal |
| Подвал | ГруппаПодвал |
vertical |
| Итоги | ГруппаИтоги |
horizontal |
| Кнопки | ГруппаКнопок |
horizontal |
| Страницы | ГруппаСтраницы / Страницы |
pages |
| Предупреждение | ГруппаПредупреждение |
horizontal, visible:false |
| Доп. секция | ГруппаДополнительно / ГруппаПрочее |
vertical, collapse |
Элементы
| Назначение | Имя |
|---|---|
| Поле в таблице | [Таблица][Поле] |
| Итог | Итоги[Поле] |
| Надпись-ссылка | [Поле]Надпись |
| Фильтр | Отбор[Поле] |
| Флажок фильтра | Отбор[Поле]Использование |
| Кнопка команды | [Команда]Кнопка |
| Баннер-картинка | [Баннер]Картинка |
| Баннер-надпись | [Баннер]Надпись |
| Подменю | Подменю[Действие] |
Обработчики событий
Имя = имя элемента + суффикс на русском:
| Событие | Суффикс | Пример |
|---|---|---|
| OnChange | ПриИзменении | ОрганизацияПриИзменении |
| StartChoice | НачалоВыбора | КонтрагентНачалоВыбора |
| Click | Нажатие | ЦеныИВалютаНажатие |
| OnEditEnd | ПриОкончанииРедактирования | ТоварыПриОкончанииРедактирования |
| OnStartEdit | ПриНачалеРедактирования | ТоварыПриНачалеРедактирования |
Обработчики формы: ПриСозданииНаСервере, ПриОткрытии, ПередЗакрытием, ОбработкаОповещения.
Принципы компоновки
- Порядок чтения. Сверху вниз, слева направо. Самое важное — вверху.
- Двухколоночная шапка. Основные реквизиты слева (контрагент, склад), организационные справа (организация, подразделение).
- Кнопки зависят от контекста. В полноэкранной форме основная команда слева вверху, в модальном окне — справа внизу; кнопка по умолчанию на форме одна.
- Таблицы — основная область. Табличные части занимают большую часть формы, обычно на Pages.
- Итоги рядом с таблицей. В подвале, горизонтальная группа, все поля readOnly.
- Фильтры — отдельная зона. Над списком, alwaysHorizontal, пара «флажок + поле» на каждый фильтр.
- Скрытые элементы для состояний. Баннеры, предупреждения —
visible: false, показываются программно. - Надписи-ссылки для диалогов.
labelFieldсhyperlink: trueи событием Click.
UX-правила для элементов и компоновки форм
Краткая адаптация 1C Design Guide: применяйте её вместе с тем, что принимают операции form.create и element.add, а не как описание неподдерживаемых элементов платформы.
Элементы
- Декорация-надпись не заменяет заголовок простого поля, не выравнивает элементы и не заканчивается точкой, если это одно предложение. Картинка берётся из библиотеки, а не из файла.
- Поле ввода имеет ширину под длинное значение, кнопку очистки для допустимого пустого значения (но не для отборов) и отдельный выбор для составного типа. Для строковых полей с доступным выбором, например пути к файлу, включайте
choiceButton. У очевидных полей можно скрыть заголовок черезtitleLocation: "none", но тогда объясните пустое значение черезinputHint. Длинный текст вводится многострочно с заголовком сверху (titleLocation: "top"); повторяющиеся значения сохраняются.
[
{ "input": "ПутьКФайлу", "path": "ПутьКФайлу", "choiceButton": true },
{ "input": "Организация", "path": "Объект.Организация", "titleLocation": "none", "inputHint": "По всем организациям" },
{ "input": "Комментарий", "path": "Объект.Комментарий", "multiLine": true, "titleLocation": "top" }
]
- У флажка заголовок справа и положительная формулировка, например «Проводить документ при записи». «Не Не проводить документ при записи» — двойное отрицание: при выключенном флажке пользователь вынужден отрицать отрицание. Для бинарного немедленного действия с заметным влиянием используйте поддерживаемый свитчер, не более 2–3 на странице:
{ "check": "Автопроведение", "path": "Автопроведение", "title": "Проводить документ при записи", "checkBoxType": "switcher" }
- Переключатель подходит для 2–5 значений, а тумблер — для 3–5 значений с короткими вариантами, когда выбор перестраивает область ниже. Текущий DSL не предоставляет отдельный нативный многозначный элемент для этого сценария: не выдавайте тумблер за такой элемент и не подменяйте его двоичным
check—checkBoxType: "tumbler"хранит один boolean. Выберите поле со списком либо запросите отдельную поддержку модели данных. - Гиперссылка открывает подчинённую или служебную форму, а не выполняет действие. Дайте ей осмысленное, достаточно длинное название; не используйте «здесь», «тут», «подробнее», не ставьте две ссылки подряд и не меняйте обычный цвет.
- Кнопка выполняет действие; для перехода используйте гиперссылку. Заголовок должен быть понятным, а для команды строки — содержать пометку. Кнопка без фигуры годится для нерекомендуемых или многочисленных команд.
- Подсказка задаётся поддерживаемыми ключами
tooltipиtooltipRepresentation; для редкой формы показывайте её сверху, для сложного реквизита — снизу, для разового знакомства — кнопкой. Подсказки не должны быть навязчивыми:
{ "button": "Сохранить", "command": "Сохранить", "tooltip": "Пояснение", "tooltipRepresentation": "Button", "defaultButton": true }
- На форме ровно одно действие по умолчанию. Для равнозначной команды визуальное выделение задаётся отдельно и не делает её действием по умолчанию:
{ "button": "Провести", "command": "Провести", "font": { "bold": true }, "backColor": "#FFFF00" }
- У табличной части заголовок в одну строку; сложное пояснение поместите в строку. Для одной колонки заголовок можно заменить декорацией. Выравнивайте заголовок колонки так же, как значения; пустая последняя колонка подавляет заголовок, доступна только для чтения и растягивается:
[
{ "input": "Сумма", "path": "Объект.Товары.Сумма", "horizontalAlign": "Right", "headerHorizontalAlign": "Right" },
{ "input": "Отступ", "title": "", "showInHeader": false, "readOnly": true, "horizontalStretch": true }
]
- Диалог содержит чёткий вопрос и текст кнопки, повторяющий действие, а закрытие крестиком возвращает отмену.
- В условном оформлении последовательно применяйте одни стили для одинаковых условий, не используйте много разных стилей и цветов и не управляйте видимостью строк.
Компоновка
- Обычная группа: проверяйте необходимость заголовка, убирайте из него слово «Группа», не полагайтесь на подсказку платформы по умолчанию, не используйте «Горизонтально, если возможно» без проверки минимального окна 1280×768. Используйте выравнивание элементов и заголовков для прижатия элементов и заголовков к краю. Сильное выделение добавляет полосу и отступ дочерним элементам; Обычное и Слабое выделение дают крупный заголовок, причём Обычное полезно для большего внешнего отступа.
- Сворачиваемая группа: скрывает необязательные, редко используемые реквизиты; заголовок описывает содержимое, обязательные и часто используемые поля в неё не помещают. Располагайте её ниже обычных групп и не отображайте отступ слева: задайте поддерживаемый JSON-ключ
"showLeftMargin": false.collapsedзадаёт начальное состояние;Группа.Показать()иГруппа.Скрыть()— только в коде формы во время выполнения, не ключи DSL. - Всплывающая группа: годится для необязательных или справочных значений, но требует говорящего заголовка и осторожности — пользователь может её не заметить. В платформе картинку управления задаёт
ControlRepresentation; DSL пока не может настроитьControlRepresentation, поэтому не изобретайте JSON-ключ или исполнимый пример. Группу можно использовать как подсказку либо как переход, оформленный подобно гиперссылке. Не помещайте туда обязательные и часто используемые поля. - Командная панель: у самостоятельной
cmdBarявно задайте источникFormдля команд формы либоFormCommandPanelGlobalCommandsдля глобальных действий; глобальную кнопку привяжите ключомcommandNameбез префиксаForm.Command.:
[
{ "cmdBar": "КомандыФормы", "commandSource": "Form", "autofill": true },
{ "cmdBar": "ГлобальныеКоманды", "commandSource": "FormCommandPanelGlobalCommands", "children": [
{ "button": "ОткрытьПараметры", "commandName": "CommonCommand.ОткрытьПараметры" }
] }
]
- При разбиении таблицы по страницам нативный DSL не устраняет дубли стандартных команд автоматически: вручную устраните дубли в нужных панелях.
- Всплывающий список может оставаться UX-решением, но не выдавайте
popupилиbuttonGroupза исполнимые нативные элементы. - Команды формы: в форме на весь экран основная команда слева вверху; в модальной форме — справа внизу. При смене страниц переопределяйте единственное действие по умолчанию для текущего шага.
- Шапка формы: располагайте поля сверху вниз и слева направо по важности; редко меняемые поля справа скрывайте по функциональным опциям. Перед выпуском проверьте, что они автозаполняются или сохраняют предыдущее значение. Не требуйте симметрии; поле, изменяющее форму, ставьте первым, а не ниже элементов, на которые оно влияет.
- Подвал формы: содержит наименее важные реквизиты и справочную информацию, в том числе итоги; в документах размещайте Комментарий и Ответственный последними.
Продвинутые паттерны (ERP)
Сворачиваемые группы
Для необязательных секций (подписи, дополнительно, прочее):
{ "group": "vertical", "name": "ГруппаПодписи", "title": "Подписи",
"behavior": "Collapsible", "collapsed": true, "children": [...] }
Баннер-предупреждение
Группа «картинка + надпись», скрыта по умолчанию, показывается программно:
{ "group": "horizontal", "name": "ГруппаПредупреждение", "showTitle": false,
"visible": false, "children": [
{ "picture": "ПредупреждениеКартинка" },
{ "label": "ПредупреждениеНадпись", "title": "Текст", "maxWidth": 76, "autoMaxWidth": false }
]}
Связанные действия командной панели
Для печати, отправки и выгрузки группируйте действия по смыслу. Нативный DSL пока не
поддерживает исполнимые элементы popup и buttonGroup; используйте отдельные
button в cmdBar либо запросите расширение модели, не копируйте JSON с этими
неподдерживаемыми ключами.
Форма без стандартной командной панели
Для модальных диалогов и мастеров:
{ "properties": { "commandBarLocation": "None", "windowOpeningMode": "LockWholeInterface" } }
Надпись-гиперссылка
Вместо кнопки для открытия подформ (ЦеныИВалюта, УчётнаяПолитика):
{ "labelField": "ЦеныИВалютаНадпись", "path": "ЦеныИВалюта", "hyperlink": true, "on": ["Click"] }
Пример: форма обработки (полный DSL)
{
"title": "Загрузка данных из CSV",
"properties": { "autoTitle": false, "windowOpeningMode": "LockOwnerWindow" },
"events": { "OnCreateAtServer": "ПриСозданииНаСервере" },
"elements": [
{ "group": "vertical", "name": "ГруппаПараметры", "children": [
{ "input": "ФайлЗагрузки", "path": "ФайлЗагрузки", "title": "Файл", "clearButton": true, "horizontalStretch": true, "on": ["StartChoice"] },
{ "input": "Кодировка", "path": "Кодировка" },
{ "input": "Разделитель", "path": "Разделитель", "title": "Разделитель колонок" }
]},
{ "table": "Данные", "path": "Объект.Данные", "on": ["OnStartEdit"], "columns": [
{ "input": "ДанныеНомерСтроки", "path": "Объект.Данные.LineNumber", "readOnly": true, "title": "№" },
{ "input": "ДанныеНаименование", "path": "Объект.Данные.Наименование" },
{ "input": "ДанныеКоличество", "path": "Объект.Данные.Количество", "on": ["OnChange"] },
{ "input": "ДанныеСумма", "path": "Объект.Данные.Сумма", "readOnly": true }
]},
{ "group": "horizontal", "name": "ГруппаКнопок", "children": [
{ "button": "Загрузить", "command": "Загрузить", "title": "Загрузить из файла", "defaultButton": true },
{ "button": "Очистить", "command": "Очистить", "title": "Очистить таблицу" },
{ "button": "Закрыть", "stdCommand": "Close" }
]}
],
"attributes": [
{ "name": "Объект", "type": "ExternalDataProcessorObject.ЗагрузкаИзCSV", "main": true },
{ "name": "ФайлЗагрузки", "type": "string" },
{ "name": "Кодировка", "type": "string(20)" },
{ "name": "Разделитель", "type": "string(5)" }
],
"commands": [
{ "name": "Загрузить", "action": "ЗагрузитьОбработка" },
{ "name": "Очистить", "action": "ОчиститьОбработка" }
]
}