Saltar al contenido principal

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​

CampoTipoObligatorioNotas
logicalNamestringsíCon el prefijo del editor, en snake_case en minúsculas.
displayNamestringsíNombre legible del formulario.
entitystringsíEl nombre lógico de la entidad propietaria.
descriptionstringnoLa línea que se muestra bajo el título en la barra de título del formulario.
iconstringnoEl icono que se muestra en la barra de título del formulario.
sectionsarrayuno de los dosUna o varias secciones con título: el diseño plano heredado (vea más abajo).
tabsarrayuno de los dosEl diseño de pestañas, más completo (vea más abajo).
actionsarraynoAcciones 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)​

CampoTipoObligatorioNotas
titlestringsíEncabezado de la sección.
columnsintegersíColumnas del diseño, 1–4.
fieldsarraysíUbicaciones de campos (vea más abajo).

Pestaña (diseño tabs)​

CampoTipoObligatorioNotas
idstringnoId estable del diseñador.
titlestringsíTítulo de la pestaña.
iconstringnoIcono que se muestra junto al título de la pestaña.
rowsarraysí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​

CampoTipoObligatorioNotas
fieldstringvea las notasEl 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.
labelstringnoEtiqueta que sustituye a la del campo; si se omite, se usa el nombre para mostrar del campo.
controlstringnoEl 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.
controlTypestringnoEl 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.
requiredbooleannoIndica 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.
readOnlybooleannoIndica 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.
controlPropsobjectnoLas 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)​

CampoTipoLo leeNotas
dateFormatstringDate, 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.
trueLabelstringCheck, ToggleLa etiqueta que se muestra para el estado «sí».
falseLabelstringCheck, ToggleLa etiqueta que se muestra para el estado «no».
rowsintegerTextAreaNúmero de filas visibles, 2–20.
lookupEntitystringLookupNombre lógico de la entidad con la que se resuelve la búsqueda.
lookupViewstringLookupNombre 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.
lookupRowCountintegerLookupCuá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.
lookupPrimaryFieldstringLookupSustitució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.
lookupSecondaryFieldstringLookupSustitució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.
lookupImageFieldstringLookupSustitució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.
imageSizestringCampo de imagenEl 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.
labelTextstringLabelEl 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.
optionsarrayDropdownOpciones 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.

CampoTipoObligatorioNotas
sourcesarray (1–10)síLas tablas que lee, una entrada por tabla (vea más abajo).
pageSizeinteger (5–100)noElementos que se muestran antes de Cargar más; 20 si falta.

Cada origen:

CampoTipoObligatorioNotas
entitystringsíEl nombre lógico de la tabla de origen.
regardingstringsí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.
datestringsí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.
titlestringsíEl campo que encabeza cada elemento.
bodystringnoUn campo del que cada elemento muestra las primeras palabras.
typestringnoUn 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.
statusstringnoUn 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" }
]
}
]
}
]
}
]
}