Definición de formulario basado en modelo
Id del esquema: model-driven-form@2
Versión reemplazada: model-driven-form@1
(model-driven-form-v1.schema.json) sigue publicada
y registrada para que una solución ya implementada se siga validando con el esquema para el que
se creó. La versión 2 solo añade el controlProps.lookupView opcional, así que toda definición
v1 es también una definición v2 válida.
Esquema legible por máquina: model-driven-form.schema.json
La representación canónica de un formulario de las aplicaciones basadas en modelo (sección 6.7): el diseño que se usa para ver y editar un único registro. Se valida de forma idéntica tanto si procede del diseñador como de una llamada a la API, de un asistente de IA o de una importación de solución.
Forma
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
logicalName | string | sí | Con el prefijo del editor, en snake_case en minúsculas. |
displayName | string | sí | Nombre legible del formulario. |
entity | string | sí | El nombre lógico de la entidad propietaria. |
description | string | no | La línea que se muestra bajo el título en la barra de título del formulario. |
icon | string | no | El icono que se muestra en la barra de título del formulario. |
sections | array | uno de los dos | Una o varias secciones con título: el diseño plano heredado (vea más abajo). |
tabs | array | uno de los dos | El diseño de pestañas, más completo (vea más abajo). |
actions | array | no | Acciones diseñables de la barra de comandos. |
Un formulario incluye o bien sections o bien tabs, pero no puede carecer de ambos. Las
definiciones nuevas deben usar tabs; sections se acepta para que los formularios existentes
sigan funcionando, y se trata como una pestaña de filas de una sola columna.
Sección (diseño heredado sections)
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
title | string | sí | Encabezado de la sección. |
columns | integer | sí | Columnas del diseño, 1–4. |
fields | array | sí | Ubicaciones de campos (vea más abajo). |
Pestaña (diseño tabs)
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
id | string | no | Id estable del diseñador. |
title | string | sí | Título de la pestaña. |
icon | string | no | Icono que se muestra junto al título de la pestaña. |
rows | array | sí | Filas de diseño a todo lo ancho: { id?, columns: 1–4, sections: [...] }, cada sección { id?, title, icon?, span?, fields, timeline? }. |
Ubicación de campo
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
field | string | vea las notas | El nombre lógico del campo (debe estar definido en la entidad). Se omite solo en una ubicación Label, que es contenido estático y no se enlaza a ningún campo. |
label | string | no | Etiqueta que sustituye a la del campo; si se omite, se usa el nombre para mostrar del campo. |
control | string | no | El nombre lógico de un control personalizado que se monta en lugar del editor de campo nativo. El control debe estar instalado en el entorno; si no lo está, el campo recurre a su editor nativo. |
controlType | string | no | El control integrado con el que se representa el campo (sección 6.13.5). Uno de Text, TextArea, Check, Toggle, Date, DateTime, Time, PersianDate, PersianDateTime, PersianTime, Lookup, Dropdown, Label. Omítalo para que el reproductor elija la entrada predeterminada del tipo de datos del campo. Las variantes Persian… muestran el mismo selector que sus equivalentes gregorianos, pero se abren en el calendario jalalí sea cual sea el idioma de la aplicación; el valor almacenado sigue siendo un instante gregoriano. Label es contenido Markdown estático (controlProps.labelText) sin campo enlazado. |
required | boolean | no | Indica si el campo es obligatorio para la empresa en este formulario (sección 6.13.5): el usuario debe rellenarlo antes de guardar. Es una cuestión del formulario, no una restricción de la base de datos (todas las columnas de la entidad admiten valores nulos); el reproductor lo aplica en el navegador y el servidor no. Si falta, se usa el IsRequired del propio campo. |
readOnly | boolean | no | Indica si el campo se muestra como de solo lectura en este formulario (visualización, no edición). Un campo de solo lectura se representa como texto sin formato, sin control de entrada. Ausente no es false: si falta, el campo es editable en una pestaña pero de solo lectura en header, así que un campo del encabezado se hace editable con un false explícito. |
controlProps | object | no | Las propiedades del control elegido (vea más abajo). |
Precedencia de controles: un control personalizado prevalece sobre controlType, que a su
vez prevalece sobre el valor predeterminado del tipo de datos del campo. Si omite ambos, el
reproductor elige el predeterminado.
La obligatoriedad es una regla del formulario, no una restricción de la columna. required
reside en la ubicación, así que el mismo campo puede ser obligatorio en un formulario y opcional
en otro, y solo se comprueba en el reproductor cuando el usuario guarda. Las columnas de la
entidad siempre admiten valores nulos en la base de datos (al estilo de Power Apps), así que un
registro creado por una importación o una llamada a la API nunca se rechaza por faltar un campo
obligatorio: el único valor que exige el servidor es el campo principal (nombre) de la
entidad.
Propiedades del control (controlProps)
| Campo | Tipo | Lo lee | Notas |
|---|---|---|---|
dateFormat | string | Date, DateTime, Time (y sus variantes Persian…) | Formato de visualización. Tokens: yyyy/yy, MMMM (nombre completo del mes)/MMM (abreviado)/MM/M, dd/d, HH, mm, ss; cualquier otro carácter es literal. Si falta, se usa el predeterminado del calendario: d MMMM yyyy para el persa (p. ej., 12 اردیبهشت 1405) y yyyy/MM/dd para el gregoriano. |
trueLabel | string | Check, Toggle | La etiqueta que se muestra para el estado «sí». |
falseLabel | string | Check, Toggle | La etiqueta que se muestra para el estado «no». |
rows | integer | TextArea | Número de filas visibles, 2–20. |
lookupEntity | string | Lookup | Nombre lógico de la entidad con la que se resuelve la búsqueda. |
lookupView | string | Lookup | Nombre lógico de la vista que proporciona las columnas que se muestran en el panel de resultados de la búsqueda. Si falta, la plataforma resuelve una: consulte el viewType del esquema de vistas. |
lookupRowCount | integer | Lookup | Cuántas filas candidatas ofrece a la vez el panel de la búsqueda (1–500). Si falta, se usa el valor predeterminado de la plataforma, 10. El servidor limita lo que se pida: un selector no es un informe. Se añadió después de v2 ampliando el esquema sin cambiar de versión: toda definición válida sin esta propiedad sigue siendo válida. |
lookupPrimaryField | string | Lookup | Sustitución, por control, del campo que es la línea de nombre de cada candidato. Si falta, se usa el propio campo principal de la tabla de destino; un nombre que no es un campo de la tabla de destino se ignora. |
lookupSecondaryField | string | Lookup | Sustitución, por control, de la segunda línea bajo el nombre, en lugar del campo que designa la tabla de destino. Si falta, se usa el que designa la tabla. |
lookupImageField | string | Lookup | Sustitución, por control, del campo File/Image que es la imagen de cada candidato, en lugar de la imagen de registro de la tabla de destino. Si falta, se usa la imagen de la tabla; un campo que no sea de imagen se ignora. |
imageSize | string | Campo de imagen | El tamaño con el que se muestra la vista previa de un campo Image: sm (predeterminado, tamaño de avatar), md o lg (una imagen destacada). Solo tiene sentido en un campo Image. |
labelText | string | Label | El texto fijo de un control Label, que se representa como un pequeño subconjunto de Markdown seguro: encabezados #/##/###, **bold**, *italic*, `code`, listas - , vínculos [text](url) (solo http/https/mailto/relativos) y {color:name}…{/color} (un nombre de color de la lista de permitidos o #hex). Nunca se representa HTML sin procesar. |
options | array | Dropdown | Opciones fijas, cada una { value, label }, que pertenecen a este único campo. Es preferible un conjunto de opciones para cualquier cosa que se reutilice entre campos o tablas: un conjunto es un componente compartido y versionado con valores a prueba de colisiones, mientras que estas opciones son una lista privada de un formulario. Un campo cuyo tipo de datos es OptionSet ignora esto y toma las opciones de su conjunto. |
Las propiedades que no se aplican al controlType elegido se ignoran, no se rechazan, de modo
que cambiar el control de un campo y volver al anterior no hace perder su configuración.
Cada field al que se hace referencia debe ser un campo definido en la entidad; esto se aplica al
guardar, además de la validación del esquema.
Sección de escala de tiempo (timeline)
Una sección de una pestaña puede ser una escala de tiempo en lugar de un grupo de campos: los
registros de otras tablas cuya búsqueda apunta al registro abierto, combinados y con los más
recientes primero; los correos electrónicos, llamadas y notas de un cliente en una sola columna.
Una sección es una cosa o la otra: cuando timeline está presente, fields debe ser una matriz
vacía.
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
sources | array (1–10) | sí | Las tablas que lee, una entrada por tabla (vea más abajo). |
pageSize | integer (5–100) | no | Elementos que se muestran antes de Cargar más; 20 si falta. |
Cada origen:
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
entity | string | sí | El nombre lógico de la tabla de origen. |
regarding | string | sí | Una búsqueda de la tabla de origen que apunta a la tabla del formulario, o una búsqueda multitabla que la incluye. La escala de tiempo muestra las filas cuyo valor es el registro abierto. |
date | string | sí | Un campo de fecha y hora del origen (incluidos los campos del sistema como created_at_utc). Los elementos se ordenan por él, con los más recientes primero. |
title | string | sí | El campo que encabeza cada elemento. |
body | string | no | Un campo del que cada elemento muestra las primeras palabras. |
type | string | no | Un campo de conjunto de opciones que distingue las filas del origen. Cada elemento toma el icono y el color de su opción, el filtro muestra una etiqueta por opción y Nuevo ofrece una entrada por opción, ya rellenada. |
status | string | no | Un campo que se muestra junto a la fecha de cada elemento. |
Al guardar y al importar, cada nombre se comprueba frente a las tablas del entorno: la tabla de
origen debe existir, regarding debe poder apuntar a la tabla del formulario, date debe ser una
fecha, type debe ser una elección y el resto debe existir. Una escala de tiempo que no cumple
cualquiera de estas condiciones se rechaza (modelapps.form.timeline_*) en lugar de mostrarse
vacía. Al eliminar un campo que usa una escala de tiempo, se quita de ella: una parte opcional se
descarta, y un origen que pierde su regarding, date o title se elimina.
Ejemplo
{
"logicalName": "par_invoice_main",
"displayName": "Main",
"entity": "par_invoice",
"description": "The invoice's main form",
"icon": "Receipt",
"tabs": [
{
"id": "tab-general",
"title": "General",
"rows": [
{
"id": "row-1",
"columns": 2,
"sections": [
{
"id": "sec-header",
"title": "Header",
"fields": [
{ "field": "par_name", "required": true },
{ "field": "par_total", "label": "Amount" },
{ "field": "par_number", "readOnly": true },
{
"field": "par_due",
"controlType": "Date",
"controlProps": { "dateFormat": "dd/MM/yyyy" }
},
{
"field": "par_paid",
"controlType": "Toggle",
"controlProps": { "trueLabel": "Paid", "falseLabel": "Unpaid" }
},
{ "field": "par_signature", "control": "par_signature_pad" }
]
}
]
}
]
}
]
}