Public
LikeselectizeInput
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v13View latest version
Widget selector reutilizable, agnóstico del lenguaje cliente (R, Python). Expone un contrato declarativo y transforma inputs heterogéneos en HTML autocontenido. Val Town no mantiene estado: solo transforma inputs en HTML.
Flujo: configuración → normalización → validación → render.
Lo que R y Python pueden enviar por POST con body JSON:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
inputId | string | null | No | Id del control (default: "selectize") |
choices | ver abajo | Sí | Opciones: vector, lista de {value, label?}, o diccionario nombrado |
selected | string | string[] | null | No | Valor o valores seleccionados (default: []) |
min_items | number | null | No | Mínimo de ítems seleccionables (default: 0) |
max_items | number | null | No | Máximo (default: número de opciones) |
- Vector simple:
["a", "b", "c"]→ value y label iguales. - Lista de objetos:
[{ "value": "a", "label": "A" }, ...]→labelopcional (si falta, se usavalue). - Diccionario nombrado:
{ "a": "A", "b": "B" }→ clave = value, valor = label.
Se tolera NULL/None en campos opcionales.
- POST /widget: body JSON con el contrato anterior. Respuesta: HTML del widget o 400 con
{ "code", "message" }. - GET /widget: para pruebas; parámetros por query (
choices,selected,inputId,min_items,max_items).choicesyselecteden JSON string.
min_items≤max_items.max_items≤ número de opciones.- Cada valor en
selecteddebe estar enchoices. - Cantidad de seleccionados entre
min_itemsymax_items.
Errores tempranos con códigos: MIN_MAX_INCOHERENT, MAX_EXCEEDS_OPTIONS, INVALID_SELECTION, BELOW_MIN_ITEMS, ABOVE_MAX_ITEMS.
shared/types.ts: contrato y modelos internos.backend/normalize.ts: RawInput → NormalizedModel.backend/validate.ts: reglas de negocio.backend/render.ts: RenderModel → HTML autocontenido.backend/index.ts: app Hono y ruta/widget.selectizeInput.http.ts: entry point HTTP (export default app.fetch).
body <- list( inputId = "mi_selector", choices = list(a = "Opción A", b = "Opción B", c = "Opción C"), selected = c("a", "b"), min_items = 1L, max_items = 3L ) httr::POST("https://.../widget", body = body, encode = "json")
import requests payload = { "inputId": "mi_selector", "choices": {"a": "Opción A", "b": "Opción B", "c": "Opción C"}, "selected": ["a", "b"], "min_items": 1, "max_items": 3, } requests.post("https://.../widget", json=payload)