Immutable. This exact content is served forever at /api/v1/blob/44cf3aa8ee479c08.
---
name: form-patterns
description: Справочник паттернов компоновки и UX-правил управляемых форм 1С. Используй как справочник при проектировании форм — архетипы, конвенции, UX-правила элементов, продвинутые приёмы
argument-hint: (no arguments)
allowed-tools: []
---
# /form-patterns — паттерны компоновки форм
Справочник типовых паттернов дизайна управляемых форм 1С. Используй **перед** проектированием формы через `unica.form.compile`, когда требования пользователя не детализируют расположение элементов.
**Как использовать:** выбери подходящий архетип, применяй конвенции именования, сверяйся с 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 | ПриНачалеРедактирования | `ТоварыПриНачалеРедактирования` |
Обработчики формы: `ПриСозданииНаСервере`, `ПриОткрытии`, `ПередЗакрытием`, `ОбработкаОповещения`.
---
## Принципы компоновки
1. **Порядок чтения.** Сверху вниз, слева направо. Самое важное — вверху.
2. **Двухколоночная шапка.** Основные реквизиты слева (контрагент, склад), организационные справа (организация, подразделение).
3. **Кнопки зависят от контекста.** В полноэкранной форме основная команда слева вверху, в модальном окне — справа внизу; кнопка по умолчанию на форме одна.
4. **Таблицы — основная область.** Табличные части занимают большую часть формы, обычно на Pages.
5. **Итоги рядом с таблицей.** В подвале, горизонтальная группа, все поля readOnly.
6. **Фильтры — отдельная зона.** Над списком, alwaysHorizontal, пара «флажок + поле» на каждый фильтр.
7. **Скрытые элементы для состояний.** Баннеры, предупреждения — `visible: false`, показываются программно.
8. **Надписи-ссылки для диалогов.** `labelField` с `hyperlink: true` и событием Click.
---
## UX-правила для элементов и компоновки форм
Краткая адаптация [1C Design Guide](https://github.com/Oxotka/1CDesignGuide/tree/edc05eaf5c191250a184b0e185006bf4b412f7a5): применяйте её вместе с поддерживаемым DSL `unica.form.compile`, а не как описание неподдерживаемых элементов платформы.
### Элементы
- Декорация-надпись не заменяет заголовок простого поля, не выравнивает элементы и не заканчивается точкой, если это одно предложение. Картинка берётся из библиотеки, а не из файла.
- Поле ввода имеет ширину под длинное значение, кнопку очистки для допустимого пустого значения (но не для отборов) и отдельный выбор для составного типа. Для строковых полей с доступным выбором, например пути к файлу, включайте `choiceButton`. У очевидных полей можно скрыть заголовок через `titleLocation: "none"`, но тогда объясните пустое значение через `inputHint`. Длинный текст вводится многострочно с заголовком сверху (`titleLocation: "top"`); повторяющиеся значения сохраняются.
```json
[
{ "input": "ПутьКФайлу", "path": "ПутьКФайлу", "choiceButton": true },
{ "input": "Организация", "path": "Объект.Организация", "titleLocation": "none", "inputHint": "По всем организациям" },
{ "input": "Комментарий", "path": "Объект.Комментарий", "multiLine": true, "titleLocation": "top" }
]
```
- У флажка заголовок справа и положительная формулировка, например «Проводить документ при записи». «Не Не проводить документ при записи» — двойное отрицание: при выключенном флажке пользователь вынужден отрицать отрицание. Для бинарного немедленного действия с заметным влиянием используйте поддерживаемый свитчер, не более 2–3 на странице:
```json
{ "check": "Автопроведение", "path": "Автопроведение", "title": "Проводить документ при записи", "checkBoxType": "switcher" }
```
- Переключатель подходит для 2–5 значений, а тумблер — для 3–5 значений с короткими вариантами, когда выбор перестраивает область ниже. Текущий DSL не предоставляет отдельный нативный многозначный элемент для этого сценария: не выдавайте тумблер за такой элемент и не подменяйте его двоичным `check` — `checkBoxType: "tumbler"` хранит один boolean. Выберите поле со списком либо запросите отдельную поддержку модели данных.
- Гиперссылка открывает подчинённую или служебную форму, а не выполняет действие. Дайте ей осмысленное, достаточно длинное название; не используйте «здесь», «тут», «подробнее», не ставьте две ссылки подряд и не меняйте обычный цвет.
- Кнопка выполняет действие; для перехода используйте гиперссылку. Заголовок должен быть понятным, а для команды строки — содержать пометку. Кнопка без фигуры годится для нерекомендуемых или многочисленных команд.
- Подсказка задаётся поддерживаемыми ключами `tooltip` и `tooltipRepresentation`; для редкой формы показывайте её сверху, для сложного реквизита — снизу, для разового знакомства — кнопкой. Подсказки не должны быть навязчивыми:
```json
{ "button": "Сохранить", "command": "Сохранить", "tooltip": "Пояснение", "tooltipRepresentation": "Button", "defaultButton": true }
```
- На форме ровно одно действие по умолчанию. Для равнозначной команды визуальное выделение задаётся отдельно и не делает её действием по умолчанию:
```json
{ "button": "Провести", "command": "Провести", "font": { "bold": true }, "backColor": "#FFFF00" }
```
- У табличной части заголовок в одну строку; сложное пояснение поместите в строку. Для одной колонки заголовок можно заменить декорацией. Выравнивайте заголовок колонки так же, как значения; пустая последняя колонка подавляет заголовок, доступна только для чтения и растягивается:
```json
[
{ "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.`:
```json
[
{ "cmdBar": "КомандыФормы", "commandSource": "Form", "autofill": true },
{ "cmdBar": "ГлобальныеКоманды", "commandSource": "FormCommandPanelGlobalCommands", "children": [
{ "button": "ОткрытьПараметры", "commandName": "CommonCommand.ОткрытьПараметры" }
] }
]
```
- При разбиении таблицы по страницам нативный DSL не устраняет дубли стандартных команд автоматически: вручную устраните дубли в нужных панелях.
- Всплывающий список может оставаться UX-решением, но не выдавайте `popup` или `buttonGroup` за исполнимые нативные элементы.
- **Команды формы:** в форме на весь экран основная команда слева вверху; в модальной форме — справа внизу. При смене страниц переопределяйте единственное действие по умолчанию для текущего шага.
- **Шапка формы:** располагайте поля сверху вниз и слева направо по важности; редко меняемые поля справа скрывайте по функциональным опциям. Перед выпуском проверьте, что они автозаполняются или сохраняют предыдущее значение. Не требуйте симметрии; поле, изменяющее форму, ставьте первым, а не ниже элементов, на которые оно влияет.
- **Подвал формы:** содержит наименее важные реквизиты и справочную информацию, в том числе итоги; в документах размещайте Комментарий и Ответственный последними.
---
## Продвинутые паттерны (ERP)
### Сворачиваемые группы
Для необязательных секций (подписи, дополнительно, прочее):
```json
{ "group": "vertical", "name": "ГруппаПодписи", "title": "Подписи",
"behavior": "Collapsible", "collapsed": true, "children": [...] }
```
### Баннер-предупреждение
Группа «картинка + надпись», скрыта по умолчанию, показывается программно:
```json
{ "group": "horizontal", "name": "ГруппаПредупреждение", "showTitle": false,
"visible": false, "children": [
{ "picture": "ПредупреждениеКартинка" },
{ "label": "ПредупреждениеНадпись", "title": "Текст", "maxWidth": 76, "autoMaxWidth": false }
]}
```
### Связанные действия командной панели
Для печати, отправки и выгрузки группируйте действия по смыслу. Нативный DSL пока не
поддерживает исполнимые элементы `popup` и `buttonGroup`; используйте отдельные
`button` в `cmdBar` либо запросите расширение модели, не копируйте JSON с этими
неподдерживаемыми ключами.
### Форма без стандартной командной панели
Для модальных диалогов и мастеров:
```json
{ "properties": { "commandBarLocation": "None", "windowOpeningMode": "LockWholeInterface" } }
```
### Надпись-гиперссылка
Вместо кнопки для открытия подформ (ЦеныИВалюта, УчётнаяПолитика):
```json
{ "labelField": "ЦеныИВалютаНадпись", "path": "ЦеныИВалюта", "hyperlink": true, "on": ["Click"] }
```
---
## Пример: форма обработки (полный DSL)
```json
{
"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": "ОчиститьОбработка" }
]
}
```