Hacer que una pantalla reaccione
Objetivo
Hacer que una pantalla dibujada haga algo: un encabezado que dice el nombre que alguien escribió, un recuadro que aparece cuando se marca una casilla, un botón Guardar que solo se activa cuando el formulario está rellenado.
Nada de eso es una imagen, y nada de eso es código que se escribe en un archivo. Es estado —el puñado de cosas que cambian mientras alguien usa la pantalla— y enlaces, que son expresiones de una línea que lo leen.
Paso 1: dar algo de estado a la pantalla
- Abra la pantalla en el diseñador (Pantallas → seleccione una → Diseñar).
- Haga clic en el propio marco de la pantalla —el cuadro más exterior— y abra la pestaña Pantalla del inspector de la derecha.
- En Estado de la pantalla, pulse Agregar un campo de estado.
- Escriba un nombre —por ejemplo
requester— y un valor inicial.
El valor inicial es una expresión, no un valor escrito sin más, así que un cuadro vacío empieza como
"" (dos comillas), una casilla como false y un contador como 0. Es el mismo lenguaje que todo lo
demás en esta pantalla, por eso solo hay una cosa que aprender.
Agregue tantos como necesite la pantalla. La mayoría de las pantallas necesitan dos o tres.
Porque dos controles leen el mismo campo. Si el estado perteneciera al cuadro desde el que se agregó, eliminar ese cuadro se llevaría el campo consigo, y todo lo demás que lo lee dejaría de funcionar sin avisar.
Paso 2: enlazar una propiedad
- Seleccione cualquier objeto del lienzo.
- En la pestaña Pantalla, en Enlaces, elija una propiedad en Enlazar una propiedad.
- Aparece un editor con un ejemplo. Sustitúyalo por su expresión.
Se pueden enlazar cuatro propiedades:
| Propiedad | Controla | En |
|---|---|---|
| Texto | lo que dice: las palabras de un encabezado, la etiqueta de un botón, el texto de marcador de posición de un cuadro | cualquier cosa |
| Se muestra | si está en la pantalla o no | cualquier cosa |
| Habilitado | si un control se puede usar | controles |
| Valor | lo que contiene un control | controles |
Todo lo demás de un objeto —dónde está, qué tamaño tiene, de qué color es— lo dibujó usted, y dibujar es la mejor forma de decir todo eso.
Ejemplos que hacen un trabajo real:
state.requester the Text of a heading
"Hello, " + state.requester the same, with words around it
state.showDetails the Shown of a panel
!state.showDetails the Shown of the line that says it is empty
state.requester != "" the Enabled of a Save button
screen.width > 700 the Shown of something a narrow window has no room for
El editor es el editor de BS Lang de la plataforma, así que subraya lo que no entiende y ofrece finalizaciones mientras escribe. Si aparece el subrayado, pase el puntero por encima para leer por qué.
Paso 3: dejar que un control escriba de vuelta
Enlace el Valor de un cuadro de texto a state.requester, y escribir en él establece
state.requester. Todo lo demás que lee ese campo lo sigue de inmediato: el saludo, el botón Guardar,
todo.
Eso es todo lo que hace que una pantalla se sienta viva, y no necesita ningún controlador.
Una regla: la escritura de vuelta solo ocurre cuando el Valor es una ruta de estado simple:
state.requester, o state.form.name. Si es calculado (state.first + " " + state.last), el control
muestra el valor y es de solo lectura, porque no hay manera de deducir, a partir de lo que alguien
escribió, los dos campos de los que procede.
Paso 4: hacer que ocurra algo al pulsar un botón
- Seleccione el botón.
- En Cuando ocurra esto, elija Pulsado en Controlar un evento.
- Escriba lo que debe ocurrir, una instrucción por línea:
notify("Ticket raised for " + getState("requester"));
setState("requester", "");
setState("showDetails", false);
Lo que puede llamar un controlador:
| Llamada | Hace |
|---|---|
setState("name", value) | cambia el estado de la pantalla; todo lo que lo lee lo sigue |
getState("name") | lo vuelve a leer, para que pueda calcular a partir de lo que hay |
loadRecords("table", "field") | carga filas de una tabla en un campo de estado; consulte más abajo |
getRecord("table", id, "field") | carga un registro por su identificador |
createRecord("table", { … }, "field") | guarda un registro nuevo; el tercer argumento es opcional |
updateRecord("table", id, { … }) | cambia los campos que nombre en un registro |
deleteRecord("table", id) | elimina un registro |
callApi("GET", "psl/v1/overview", { … }, "field") | pregunta a una Custom API y guarda su respuesta — vea Cifras de una Custom API |
notify("…") / notifyError("…") | avisa a la persona que usa la pantalla |
showModal("Card") / closeModal() | muestra una tarjeta superpuesta sobre la pantalla; consulte el paso 5 |
openStartDrawer("Card") / closeStartDrawer() | desliza una desde el borde inicial |
openEndDrawer("Card") / closeEndDrawer() | y desde el borde final |
openDropdown("Card") / closeDropdown() | abre una junto a lo que se haya pulsado |
setVisualState("name") | pone en ese estado el objeto más cercano por encima de este controlador que tenga un estado dibujado; "" vuelve a Normal; consulte Reutilizar un diseño con componentes |
openUrl("…", "newTab") | va a una dirección web; omita el segundo argumento para quedarse en esta ventana |
navigate("Screen") | va a otra pantalla de esta aplicación, por el nombre de su marco |
reloadSurfaces() | vuelve a mostrar cada tabla o formulario integrado de esta pantalla, con datos nuevos |
Un controlador es un pequeño programa, no una expresión. Puede cambiar cosas —para eso existe— y puede tener tantas líneas como necesite. Esa es la diferencia con un enlace, que solo lee.
Los demás eventos están ahí cuando los necesite: Pulsado dos veces, Valor cambiado (en un control), Recibe el foco, Pierde el foco, Llega el puntero, Sale el puntero y, en el propio marco de la pantalla, Se abre la pantalla, que se ejecuta una vez, después de que exista el estado.
Un controlador que solo cambia el color de algo cuesta trabajo en cada movimiento del puntero. Un estado dibujado no cuesta nada en absoluto, porque lo hace el navegador. Consulte Reutilizar un diseño con componentes.
Ir a otra pantalla de la aplicación
Una aplicación contiene varias pantallas, y navigate se mueve entre ellas:
navigate("Details");
navigate("Details", { id: getState("chosen") });
El nombre es el nombre del marco de la pantalla, exactamente como lo escribió ahí: cambie el
nombre del marco y cada navigate que nombre el nombre antiguo deja de funcionar, algo que la
pantalla le indica al pulsarlo en lugar de fallar sin avisar.
Qué sobrevive al cambio y qué no. La pantalla que deja se cierra: su estado desaparece, así que al
volver obtiene uno nuevo; un formulario a medio rellenar no debería seguir a medio rellenar, y una
pantalla que cargaba filas al llegar vuelve a cargarlas. Lo que viaja es lo que usted entrega: el
segundo argumento llega como screen.params, así que screen.params.id en la pantalla siguiente lee
lo que envió.
Siempre es screen.params. No existe un params más corto, y el editor de código lo subraya.
La barra de direcciones le sigue. Cada pantalla tiene su propia URL, así que el botón Atrás del
navegador vuelve a la pantalla anterior, una recarga vuelve a la misma y un enlace que copie se abre
ahí. Los valores entregados no viajan de esa forma —llegar con Atrás, recargando o con un enlace
pegado abre la pantalla sin screen.params—, así que trátelos como una entrega entre dos pantallas y
no como algo que pueda llevar un enlace.
Leer y escribir registros
Cinco llamadas, y entre ellas son lo que convierte un dibujo en una aplicación.
Leer una lista:
loadRecords("par_ticket", "tickets");
loadRecords("par_ticket", "tickets", 20);
loadRecords("par_ticket", "tickets", { top: 20, where: { par_status: "Open" }, orderBy: "par_name" });
Las filas llegan al campo de estado que indicó, y todo lo demás de la pantalla ya sabe qué hacer con
ellas: una tabla se repite sobre state.tickets, un rótulo lee state.tickets.length(). Consulte
Dibuje una fila, obtenga una por registro.
El tercer argumento es o bien cuántas como máximo, o bien la pregunta completa: top, where,
orderBy y descending. where solo compara por igualdad, y cada par que escriba tiene que
coincidir. Cuando necesite más que eso —un intervalo, «contiene», un o—, construya una vista con
el diseñador de consultas y dibuje la pantalla sobre ella en lugar de meterlo todo en una línea aquí.
Leer uno:
getRecord("par_ticket", screen.params.id, "ticket");
Es la pareja de navigate("Details", { id: row.id }): la pantalla de lista entrega el identificador,
y la pantalla de detalles obtiene el registro que hay detrás. Si ese registro ya no existe, el campo
se deja como estaba en lugar de vaciarse, así que los enlaces que dependen de él siguen funcionando.
Escribir:
createRecord("par_ticket", { par_name: getState("title"), par_status: "Open" });
createRecord("par_ticket", { par_name: getState("title") }, "created");
updateRecord("par_ticket", getState("ticket").id, { par_status: "Closed" });
deleteRecord("par_ticket", getState("ticket").id);
El tercer argumento de createRecord es opcional y a menudo merece la pena escribirlo: la
plataforma responde con el registro que guardó, identificador incluido, así que
getState("created").id es como la pantalla abre o actualiza después lo que acaba de crear. Sin él no
hay forma de conocer ese identificador.
Los nombres de campo son los nombres lógicos de las columnas de la tabla —par_name, no Nombre—,
los mismos que muestra el diseñador de tablas.
Nada le indica a la persona que usa la pantalla que una escritura ha funcionado, así que dígalo usted:
createRecord(…); notify("Ticket raised");. Si la plataforma rechaza la escritura —un campo
obligatorio, un permiso—, la pantalla muestra el motivo que dio, por eso merece la pena leer el mensaje
en lugar de sustituirlo.
Y el resto de ese clic se detiene, así que un notify o un navigate después de la escritura solo ocurre si funcionó.
Cada una de estas llamadas se comprueba contra los permisos de quien esté usando la aplicación, en cada llamada. Ocultar un botón Eliminar oculta un botón; no impide nada.
openUrl es para cuando la pantalla decide adónde ir: después de guardar, o según lo que se haya
elegido. Cuando el destino simplemente se conoce, dibuje un enlace en su lugar: el clic central, el
clic derecho → Abrir en una pestaña nueva y la lista de enlaces de un lector de pantalla funcionan en
un enlace real y en nada más. Consulte
Dibujar una aplicación de Studio.
Cifras de una Custom API
Una cifra — las reservas de hoy, los ingresos de este mes — es un intervalo y una suma, a menudo
sobre varias tablas, y loadRecords no puede pedirla. Calcúlela en una Custom API y llámela desde
la pantalla:
callApi("GET", "psl/v1/overview", { date: "2026-10-06" }, "figures");
La dirección es la de la propia API dentro del entorno: su prefijo de editor, su versión y su
ruta. Con GET las entradas viajan como cadena de consulta; con POST y los demás, como cuerpo.
La respuesta llega al campo de estado que indique, así que un texto enlazado a
state.figures.bookingsToday la muestra. La API se ejecuta con los permisos de quien usa la pantalla.
Una página de portal lee las tablas que su portal enumera y nunca nombra una API, así que allí
callApi muestra un mensaje en lugar de una respuesta.
Cuando el cuadro se queda pequeño: la página de código
Un enlace es una línea y pertenece junto a lo que controla. Un controlador crece, y después del tercer
if el pequeño editor del panel es una ranura de buzón.
Seleccione primero el objeto y después pulse Escribir código en la barra de herramientas (el
botón </>). El diseñador queda cubierto —la página a su alrededor se mantiene— por una lista de
todo lo que se puede programar en ese objeto, en el lateral, y un editor con espacio para
escribir. La lista contiene sus enlaces, sus controladores, los campos de estado de la pantalla y las
propiedades propias de un componente. También aparecen los que están sin escribir, que es la respuesta
más rápida a «¿qué podría poner en esto?».
La lista indica cuáles están escritos, así que nunca tiene que abrir uno para averiguarlo:
| Junto al nombre | Significa |
|---|---|
| Un punto verde, nombre en negrita | Escrito, y tiene sentido |
| Un punto rojo, nombre en negrita | Escrito, y tiene un error: ábralo y el editor subraya dónde |
| Un punto hueco, nombre atenuado | Todavía no hay nada escrito |
Mientras la página de código está abierta, el teclado es del editor. Escribir t escribe una t;
no activa la herramienta Texto que hay detrás de la página.
Para volver, pulse Diseñar: el mismo botón que le devuelve de una vista previa, en el mismo sitio de la parte superior de la página. El dibujo está exactamente como lo dejó: la misma selección, el mismo zoom. Y es el mismo documento en ambos casos, así que un controlador escrito aquí aparece en el panel de allí.
Si no ocurre nada al pulsarlo, un mensaje explica por qué, y solo hay tres motivos:
| El mensaje | Qué hacer |
|---|---|
| No hay nada seleccionado, o hay más de una cosa | Seleccione exactamente un objeto |
| El código se escribe en el propio componente | Tiene seleccionada una copia (una instancia) o una variante. Clic derecho → Ir al componente principal y escríbalo ahí: todas las copias lo reciben |
| Este objeto forma parte del gráfico de la pantalla | Indique primero qué es en la pestaña Pantalla —un botón, un cuadro de texto— y entonces tendrá controladores que escribir |
Un componente se escribe en su copia principal. Seleccione el marco del que está hecho el componente —no una copia en una pantalla— y la lista ofrece Pulsado y el resto, exactamente igual que para cualquier otra cosa. Ahí es donde pertenece el comportamiento de un componente: escríbalo una vez, y cada copia en cada pantalla lo hace.
Paso 5: preguntar antes de hacer algo, en un cuadro modal, una lista desplegable o un panel lateral
Una tarjeta superpuesta es una parte de la pantalla que no está ahí hasta que un controlador la muestra.
-
Dibuje su contenido una vez, como componente. Una tarjeta con una pregunta y dos botones es un componente como cualquier otro —consulte Reutilizar un diseño con componentes—, así que la misma confirmación puede usarse en cada pantalla que la necesite. Dibújela junto a su pantalla, donde haya espacio.
-
Seleccione el componente y marque Una tarjeta superpuesta en la pestaña Gráfico. Esa es toda la configuración: deja de dibujarse en la pantalla y pasa a ser algo que un controlador puede mostrar.
-
Muéstrela desde un controlador, por el nombre del propio componente:
Llamada Dónde aparece Útil para showModal("Confirm card")centrada sobre la pantalla, con un fondo una pregunta que hay que responder antes que nada openDropdown("Menu card")unida a lo que se pulsó un menú pequeño, una indicación, un formulario breve openStartDrawer("Filters card")a toda altura, deslizándose desde el borde inicial filtros, un menú en una ventana estrecha openEndDrawer("Details card")a toda altura, desde el borde final un panel de detalles -
Ciérrela con
closeModal(),closeDropdown(),closeStartDrawer()ocloseEndDrawer(); desde un botón dentro de ella, por ejemplo. Un panel lateral no tiene botón de cerrar propio: dibuje uno en la tarjeta, como hacen los menús de los ejemplos. Esc y un clic junto al panel lo siguen cerrando.
Una tarjeta que hay que responder
Debajo de la marca Una tarjeta superpuesta hay una segunda: Hay que responderla. Con ella activada, hacer clic fuera de la tarjeta, pulsar Esc y el botón de cerrar dejan de funcionar mientras está abierta, y el botón de cerrar ni siquiera se muestra, porque un control que está visiblemente ahí y no hace nada parece una página congelada a quien lo pulsa dos veces.
Déjela desactivada salvo que la tarjeta pregunte algo que marcharse no puede responder. Una superposición que alguien abrió por accidente debe cerrarse igual que se abrió; el único tipo que no debe hacerlo es el que existe para obtener una respuesta —«¿eliminar estos cuatro registros?», «otra persona cambió este registro, ¿cuál conservar?»—, donde hacer clic en el fondo no es una respuesta y sin embargo lo parece.
Dibuje su propia salida. Una tarjeta obligatoria rechaza todas las formas de cerrarla que ofrece la
plataforma, así que necesita un botón propio que ejecute closeModal(), closeStartDrawer() o
closeEndDrawer(). Póngalo primero y sin énfasis, como un Cancelar junto a un Eliminar.
Una lista desplegable la ignora. Un menú que no se puede cerrar haciendo clic fuera ha atrapado la página, y una lista desplegable nunca es la forma de hacer una pregunta.
Una lista desplegable se abre junto a lo que ejecutó el controlador. No hay nada que elegir: ponga
openDropdown("Menu card") en el botón, y el menú aparece junto a ese botón.
Dónde respecto a él, lo puede indicar: openDropdown("Menu card", "bottom-end"):
| Ubicación | Dónde va la tarjeta |
|---|---|
"bottom" (el valor predeterminado) | debajo del botón, centrada en él |
"bottom-start" / "bottom-end" | debajo, alineada con su borde inicial / final |
"top", "top-start", "top-end" | encima: para un control cerca de la parte inferior de una pantalla |
end, no right. Una tarjeta abierta con bottom-end cuelga del borde derecho del botón en
inglés y de su borde izquierdo en persa y árabe, que es la misma regla que siguen los paneles
laterales: un solo script pone el menú en el lado correcto en todos los idiomas. Escribir
"bottom-right" daría una pantalla al revés en persa sin nada que lo advirtiera; por eso no es una
ubicación, y a un controlador que la pida se le avisa.
Está expresando una preferencia, no una promesa: si no hay espacio debajo, el menú se abre encima de todos modos. Un menú que se sale de la pantalla es peor que un menú en el otro lado.
Su ancho es el ancho con el que la dibujó. El ancho propio de la tarjeta es el ancho del panel lateral y el del cuadro modal, así que haga la tarjeta del tamaño que quiera que tenga el panel.
Hay uno de cada, y mostrar una segunda tarjeta sustituye a la primera. Una pantalla solo puede tener un cuadro modal abierto a la vez, por eso no hay nada que declarar: los contenedores siempre están ahí y su controlador dice qué va en uno.
El borde de un panel lateral sigue al idioma, no al dibujo. Inicial es la izquierda para quien lee en inglés y la derecha para quien lee en persa o árabe: toda la pantalla se refleja, porque en una aplicación lo que usted dibujó es el marco.
Esc, el fondo y un clic fuera cierran todos una superposición, y el foco vuelve a lo que la abrió. Nada de eso es algo que usted configure.
Paso 6: obtener una vista previa
Pulse Vista previa. La vista previa es el tiempo de ejecución real —el mismo componente que monta el Shell, no una aproximación—, así que lo que ve es lo que ve alguien que usa la aplicación.
Escriba en los cuadros. Observe cómo le sigue el resto de la pantalla.
Reglas que conviene conocer
Un enlace solo lee. Se vuelve a ejecutar cada vez que cambia lo que lee, así que un enlace que cambiara algo se reiniciaría continuamente. El diseñador lo rechaza al Guardar y le indica qué objeto y qué propiedad: todo lo que cambia algo pertenece a un controlador.
«Se muestra» quita, no oculta. Un elemento cuyo Se muestra es falso no está en la página en absoluto: nada llega a él con el tabulador, ningún lector de pantalla lo anuncia y Ctrl+F no lo encuentra. Casi siempre es lo que quería decir.
Nada de esto es seguridad. Un botón oculto es un botón oculto. Lo que una persona puede hacer realmente se decide en el servidor, cada vez, muestre lo que muestre la pantalla.
Lo que puede ver un enlace, hoy
| Nombre | Es |
|---|---|
state | el propio estado de la pantalla, del paso 1 |
screen | screen.width y screen.height —la superficie, para que una pantalla pueda reaccionar a una ventana estrecha— y screen.name, la pantalla en la que está, para que una barra colocada en todas las pantallas pueda marcar su propia página |
ui | ui.theme (light o dark), ui.locale (en, fa, ar) y ui.dir (ltr o rtl): los propios ajustes del lector |
user | quién ha iniciado sesión: user.name, user.email y user.photo (vacío si no tiene foto, así que vincule el Shown de una imagen a user.photo != ""): suficiente para un saludo o una barra superior, y a propósito sin sus roles |
screen.params | lo que entregó la pantalla que le envió aquí: navigate("Details", { id }) |
Los registros llegan a través de un controlador, no mediante un nombre propio. loadRecords y
getRecord los ponen en el propio estado de la pantalla, así que un enlace lee state.tickets como
cualquier otra cosa: no hay un segundo sitio donde mirar. Lo que de verdad todavía no está aquí son las
vistas guardadas de la plataforma: una pantalla nombra una tabla y un where, no una vista.
Lo que puede calcular un enlace
Un enlace es una expresión, así que no puede hacer bucles ni llamar a setState. Unas pocas funciones
pequeñas cubren lo que suele necesitar un rótulo además de la aritmética:
| Función | Responde |
|---|---|
text(value) | el valor como palabras, para que un número pueda ir dentro de una frase: "of " + text(state.total) |
num(value) | las palabras como número: lo que devuelve una lista desplegable, listo para la aritmética; 0 si no es un número |
first(list, { field: value, … }) | la primera fila de una lista cargada cuyos campos contienen esos valores, o null: first(state.budgets, { par_department: state.department, par_category: state.category }) |
format(value, "integer" | "number" | "percent") | un número tal como lo escribe su idioma: format(174500, "integer") es 174,500 en inglés y usa dígitos persas en persa |
translate({ en: "…", fa: "…", ar: "…" }) | las palabras en el idioma del lector, con el inglés como alternativa; consulte Dos idiomas |
first es como un rótulo sigue a un selector hasta la fila que nombra. Cargue la tabla una vez, en
Se abre la pantalla; después
"Available: £" + format(first(state.budgets, { … }).par_remainingbudget, "integer") sigue a dos
listas desplegables vayan donde vayan, sin ningún controlador. Una fila cargada lleva una columna de
opción como su etiqueta, y una lista desplegable devuelve la etiqueta que ofreció, así que las dos
coinciden. Proteja el caso en que nada coincide con un condicional —first(…) == null ? "Choose a line" : …—, porque leer un campo de null hace fallar el enlace, y && no lo protege: los dos lados de un
&& se evalúan siempre.
Un intervalo es trabajo de un controlador. first compara valores exactos; «el tramo cuyo mínimo y
máximo engloban este importe» es un bucle, y un bucle pertenece al controlador Valor cambiado del
control, que escribe lo que encontró en el estado para que lo lea el rótulo. El ejemplo
studio-capital-planning de samples/solutions hace las dos cosas en una pantalla.
Dos idiomas en una pantalla
Enlace el Texto de un texto a translate(...), con cada idioma junto al inglés:
translate({ en: "Opening times", fa: "ساعات کار" })
y dé a la página un botón que cambie: if (ui.locale == "fa") { setLanguage("en"); } else { setLanguage("fa"); }.
setLanguage cambia el idioma de la plataforma, no solo el de la pantalla: se recuerda, y en persa
o árabe toda la página se refleja, porque cada posición que dibuja una pantalla es inicial y final
y no izquierda y derecha. ui.dir indica en qué dirección se lee, para que una flecha pueda apuntar
hacia el lado correcto.
Un idioma que el objeto no tiene recurre al inglés, así que una página a medio traducir se lee en inglés y no con huecos. El ejemplo portal-pages-and-navigation está escrito así, palabra por palabra.
Algo que ocurre por sí solo: el temporizador
Dé a un objeto un controlador Tic del temporizador y enlace su Intervalo del temporizador (ms): ejecuta ese controlador cada tantos milisegundos mientras el objeto está en la página:
Timer interval (ms): state.held ? 0 : 5000
Timer ticks: setState("slide", (getState("slide") + 1) % 3);
Cero, o nada, es detenido, así que pausar forma parte del enlace, y un carrusel que se detiene
mientras lo señala establece held en sus controladores Llega el puntero y Sale el puntero. Menos
de 250 se sube a 250. Un objeto oculto no hace tic. El carrusel de la biblioteca de componentes, y el de
la página de inicio de portal-pages-and-navigation, están construidos así.
Solución de problemas
- «No se pudo ejecutar un enlace en …» — la expresión es válida, pero algo que nombra no está. La causa más habitual es un campo de estado escrito de forma distinta en el enlace: compruebe la lista Estado de la pantalla del marco de la pantalla.
- El cuadro no me deja escribir. — su Valor es una expresión calculada, así que es de solo lectura por diseño. Enlácelo a un campo de estado simple y calcule la otra cosa en otro sitio.
- No ocurre nada al escribir. — el cuadro no tiene enlace de Valor. Un cuadro sin enlace se queda con lo que se escribe y no se lo dice a nadie.
- El botón Guardar nunca se activa. — compruebe su expresión Habilitado con un valor vacío:
state.requester != ""solo es verdadero cuando se ha escrito algo. - Pulsar el botón no hace nada. — un control deshabilitado no recibe ninguna pulsación, así que compruebe primero su enlace Habilitado; después compruebe que el controlador está en Pulsado y no en un evento que aquí nunca se dispara (Se abre la pantalla pertenece al marco de la pantalla, Valor cambiado a un control).
- «No se pudo ejecutar un controlador en …» — el controlador es BS Lang válido, pero algo que
nombra no está. La causa más habitual es
setStateen un campo que la pantalla nunca declaró. - «createRecord("…") falló: …» — la plataforma rechazó la escritura, y lo que sigue a los dos puntos es su propio motivo: un campo obligatorio sin nada, un valor que no es una de las opciones o un permiso que usted no tiene. Compruebe primero los nombres de campo con el diseñador de tablas: un nombre lógico mal escrito es la causa más habitual.
- No se carga nada, y nada se queja. — está en Vista previa, que no tiene ningún entorno detrás. Las llamadas a registros no hacen nada ahí, a propósito. Abra la aplicación desde el Shell para ver registros reales.
showModal("…")no hace nada. — el nombre tiene que coincidir exactamente con el nombre del componente, y el componente tiene que tener marcada Una tarjeta superpuesta. Una tarjeta que se eliminó, o a la que se cambió el nombre, deja controladores que la nombran, y estos no hacen nada sin avisar en lugar de romper la pantalla.- La tarjeta se muestra en la pantalla en lugar de en un cuadro modal. — Una tarjeta superpuesta no está marcada. Hasta que lo esté, el componente se dibuja donde lo puso, como cualquier otro componente.
- «Dos componentes se llaman …» — una tarjeta se muestra por el nombre de su componente, así que
dos que compartan nombre son una pregunta que
showModalno puede responder. Cambie el nombre de uno.
Pruébelo
Importe la solución de ejemplo Ticket Triage. Es esta página, ya construida: tres campos de estado, propiedades enlazadas por todas partes, un estado al que el propio ejemplo dio nombre, un cuadro modal que pregunta antes de plantear la incidencia y un elemento emergente que se abre desde su propio botón.