Saltar a contenido

Campos de formulario v1

Declara campos con FormBuilder / FieldBuilder; el framework emite JSON Schema + UI schema y el widget form los renderiza en @cortex/panel-shadcn.

Pipeline

FieldBuilder → FormDefinition (+ uischema) → GET /api/v1/forms/{formId} → FormWidget

Emisión centralizada: framework/cortex_framework/forms/emit.py.

Tipos de campo

Método Tipo SPI Uso
.text() string Texto corto
.textarea() textarea Texto largo
.email() email Correo
.password() password Contraseña
.integer() integer Entero
.number() number Decimal
.money() money Monto (currency, default COP)
.boolean() boolean Checkbox
.toggle() toggle Interruptor
.date() date Fecha
.datetime() datetime Fecha y hora
.time() time Hora
.hidden() hidden Valor oculto (default)
.select() select Lista cerrada con labels
.radio() radio Opción única
.checkbox_list() checkbox_list Múltiple → string[]
.tags() tags Chips libres
.color() color Color hex
.file() file Archivo → URL (upload S3)
.image() image Imagen con preview
.relationship() relationship BelongsTo async (path, label_key, value_key)
.repeater() repeater Array de sub-objetos
.key_value() key_value Objeto clave-valor dinámico
.rich_text() rich_text HTML (Tiptap)
.markdown() markdown Markdown con preview
.computed() computed Solo lectura, derivado en cliente

Parámetros comunes: required=True, placeholder, helper_text, visible_when={"field": "x", "equals": value}.

Layouts

f.section("General", lambda b: b.text("name", "Nombre"))
 .section("Avanzado", lambda b: b.text("code", "Código"), collapsed=True)
 .columns(2, lambda b: b.text("a", "A").text("b", "B"))
 .tabs({"General": lambda b: b.text("name", "Nombre"), "Extra": lambda b: b.text("sku", "SKU")})

Upload S3

Configura en el framework:

  • CORTEX_UPLOAD_BUCKET
  • CORTEX_UPLOAD_REGION (default us-east-1)
  • CORTEX_UPLOAD_PREFIX (default cortex)
  • CORTEX_UPLOAD_PUBLIC_BASE_URL (URL pública opcional)

Endpoint: POST /api/v1/uploads{ "url", "key" }.

Ejemplo

.form(
    lambda f: (
        f.text("name", "Nombre", required=True)
        .money("amount", "Monto")
        .select("status", "Estado", options=(("open", "Abierto"), ("closed", "Cerrado")))
        .repeater("lines", "Líneas", lambda b: b.text("desc", "Descripción").money("price", "Precio"))
    )
)

Demo

Plugin reference registra form-demo con todos los tipos: GET /api/v1/forms/form-demo.

Siguiente paso

Columnas de tabla.