Saltar al contenido principal

Construir su primera aplicación de Studio

Objetivo​

Construir desde cero una aplicación que funcione: una tabla que contenga los registros, una pantalla que los muestre, una barra de herramientas que actúe sobre el que marque y un panel que vuelva a escribir un registro nuevo.

La primera vez lleva unos cuarenta minutos. Nada de esto es un juguete: cada paso es el que daría para una aplicación real, y lo que obtiene al final es, a grandes rasgos, el ejemplo Support desk.

Lea primero el resultado terminado

studio-starter-app en samples/solutions es esta aplicación, ya dibujada. Impórtela desde Soluciones → Importar, ábrala y pulse cosas. Volver aquí después de eso acorta cada uno de los pasos siguientes.

Antes de empezar​

  • Ha iniciado sesión como creador.
  • Hay un entorno y una solución seleccionados en los selectores de la parte superior de la página. Nada de lo que cree a continuación existe fuera de ellos.
  • Conoce el prefijo del editor de su solución: las dos o tres letras que van delante de cada nombre lógico. Esta página escribe par; el suyo puede ser distinto.

1. Una tabla que contenga los registros​

Una aplicación que no muestra nada es un dibujo. Cree primero la tabla.

Tablas → Nuevo, y rellene:

CampoValor
Nombre para mostrarCase
Nombre en pluralCases
Nombre lógicopar_case (el prefijo se agrega automáticamente)
Campo principalSummary

Guarde y después agregue tres campos más en la pestaña Campos:

Nombre para mostrarNombre lógicoTipo
Prioritypar_priorityOpción: nuevo conjunto de opciones par_case_priority, con las opciones Low, Normal, High
Urgentpar_urgentSí/No
Notespar_notesTexto multilínea
Un campo Sí/No empieza como nada, no como No

Un registro creado sin tocar Urgent no tiene ningún valor para él, y ningún valor no es un booleano. Así que una expresión como record.par_urgent ? "Yes" : "No" falla con Only booleans are allowed in this expression precisamente en esos registros. Escriba (record.par_urgent ?? false) allí donde lea un campo opcional, y el problema desaparece. Es la sorpresa más habitual en una primera aplicación.


2. La aplicación​

Aplicaciones de Studio → Nuevo:

CampoValor
Nombre para mostrarSupport desk
Nombre lógicopar_support
DescripciónUna frase. Es lo que muestra el mosaico del iniciador bajo el nombre.
IconoPulse el selector y elija uno: LifeBuoy encaja con una aplicación de soporte
Mostrada en el Shellactivado

Pulse Guardar y después Diseñar. Se abre el lienzo.


3. La pantalla, y qué es una pantalla​

Dibuje un marco que ocupe el lienzo —unos 1200 × 760 es un tamaño de dibujo cómodo— y, con él seleccionado, abra la pestaña Pantalla del inspector de la derecha:

┌─ Inspector ───────────────────────┐
│ Graphic │ Screen │ Code │
├───────────────────────────────────┤
│ This object is … │
│ ┌─────────────────────────────┐ │
│ │ The screen ▾ │ │ ← choose this
│ └─────────────────────────────┘ │
│ │
│ Content that does not fit │
│ ┌─────────────────────────────┐ │
│ │ Show it — it spills out ▾ │ │
│ └─────────────────────────────┘ │
└───────────────────────────────────┘

Cambie el nombre del marco a Cases en el panel Capas. Ese nombre es el nombre de la pantalla: es lo que pedirá después navigate("Cases").

El tamaño que dibujó no es el tamaño final. Todo lo que hay dentro está anclado a los bordes del marco, y el marco llena la ventana en la que se abra la aplicación, sea cual sea.


4. La memoria propia de la pantalla​

Una pantalla recuerda cosas: en qué página de la lista está, qué se escribió en el cuadro de búsqueda, qué filas están marcadas. Esa memoria es el estado de la pantalla, y se declara una vez en el marco de la pantalla.

Con el marco de la pantalla seleccionado, en la pestaña Pantalla, agregue lo siguiente en Estado:

NombreEmpieza como
cases[]
caseTotal0
page0
pageSize20
picked""
pickedCount0
pickedId""
form{ par_name: "", par_urgent: false, par_notes: "" }

Declare la forma de form; no lo deje en {}. Un enlace que lee un miembro que un objeto no tiene produce un error, y la primera evaluación de la pantalla se ejecuta antes de que nada haya rellenado el formulario.


5. Rellenar la lista​

Todavía en el marco de la pantalla, en la pestaña Pantalla, busque Controladores y ponga esto en Cargado:

loadRecords("par_case", "cases", {
top: getState("pageSize"),
skip: getState("page") * getState("pageSize"),
orderBy: "par_name",
countInto: "caseTotal"
});

Una línea de consulta es toda la paginación: top y skip son la página, y countInto devuelve cuántas filas hay en total, algo que una página de veinte no puede decir y que un botón Siguiente tiene que saber. Consulte Mostrar una lista página a página para el resto.

Todavía no se ve nada. No hay nada dibujado en lo que mostrarlo.


6. Una fila, dibujada una vez​

Este es el paso que sorprende a la gente, así que merece la pena decirlo claramente: usted dibuja una fila, y la plataforma dibuja una por registro.

  1. Dibuje un marco dentro de la pantalla para la lista: todo el ancho del contenido y unos cientos de píxeles de alto. Llámelo Rows. En la pestaña Pantalla establezca Este objeto es → Una lista y Contenido que no cabe → Desplazarse hasta él, y después En qué dirección se desplaza → Hacia abajo. Un cuadro dibujado para seis filas contiene cien en cuanto tiene detrás una tabla real.

  2. Dele diseño automático, vertical, en la pestaña Gráfico. Sin él, cada copia de la fila cae encima de la primera.

  3. Dibuje un marco dentro de Rows, de todo el ancho y 64 de alto. Llámelo Case row y establezca Este objeto es → Un elemento de lista.

  4. Con Case row seleccionado, busque Repetir para cada en la pestaña Pantalla y escriba:

    state.cases
  5. Dibuje un objeto de texto dentro de la fila para el resumen. Selecciónelo y, en Enlaces, establezca Texto:

    row.par_name

row es el registro de esta copia. Guarde y pulse Vista previa: una fila por caso, desde la tabla, sin nada repetido a mano.

┌─ Rows ────────────────────────────────────────────────┐
│ ☐ 1 Sample case 1 Normal │ ← Case row, drawn once
│ ☐ 2 Sample case 2 High Urgent │
│ ☐ 3 Sample case 3 Low │
│ … │
└───────────────────────────────────────────────────────┘

7. La marca, y una sola idea de qué está elegido​

Dibuje un marco pequeño al principio de la fila, de 20 × 20, y establezca Control → Casilla. Después:

  • Enlaces → Valor: state.picked.includes(row.id)

  • Controladores → Cambiado:

    var ids = "";
    var count = 0;
    var firstId = "";
    var i = 0;
    for (i = 0; i < state.cases.length(); i = i + 1) {
    var id = state.cases[i].id;
    var on = state.picked.includes(id);
    if (id == row.id) { on = !on; }
    if (on) {
    ids = ids + id + "|";
    count = count + 1;
    if (count == 1) { firstId = id; }
    }
    }
    setState("picked", ids);
    setState("pickedCount", count);
    setState("pickedId", firstId);

El valor es una comparación, no un campo. Cada casilla vuelve a leer la única lista, así que vaciar la lista desmarca todas a la vez, cosa que un indicador por fila nunca podría hacer, porque nada sabría dónde estaban las demás filas.


8. Una barra de herramientas que se activa​

Dibuje una barra encima de la lista —un marco, de todo el ancho y 56 de alto, Este objeto es → Una región— y ponga tres botones en ella. Para cada uno: dibuje un marco, establezca Control → Botón y dibuje dentro un objeto de texto para el rótulo.

Ponga un glifo en cada uno. Seleccione el botón y use el selector de iconos de la pestaña Gráfico: Plus, Pencil, Trash2. Lo que llega es un trazado dibujado normal dentro del botón, y el botón terminado dispone por sí mismo el glifo, el espacio y el rótulo.

BotónEnlaces → HabilitadoControladores → Pulsado
Nuevo(déjelo vacío)setState("form", { par_name: "", par_urgent: false, par_notes: "" });
openEndDrawer("New case");
Editarstate.pickedCount == 1openStartDrawer("Edit case");
Eliminarstate.pickedCount > 0showModal("Confirm delete");

Enlace Habilitado en lugar de escribir código para atenuar las cosas. Un enlace se vuelve a evaluar cada vez que cambia el estado, así que la barra se activa y se desactiva por sí sola.

Pinte el texto y el borde del botón Eliminar con el token color.error, no con un rojo que haya elegido usted. Un token sigue el modo de color del lector; un valor hexadecimal es correcto para quien lo dibujó y erróneo para todos aquellos cuyo tema es distinto.


9. El panel lateral, y qué es una tarjeta superpuesta​

Una superposición no es una pantalla. Es un componente que usted marca como tarjeta, y un controlador decide dónde se abre.

  1. Dibuje el formulario en algún lugar alejado de la pantalla: un marco de unos 420 de ancho, con un título, los campos y dos botones. No importa en qué parte del lienzo esté; una tarjeta se compila en el origen, y solo se conserva su ancho.
  2. Seleccione el marco, pulse Crear componente y llámelo New case.
  3. En el panel del componente, marque Una tarjeta superpuesta.
┌─ Inspector · Component ───────────┐
│ ☑ An overlay card │
│ Show it with showModal("New │
│ case") … Its drawn width is │
│ the panel's width. │
│ │
│ ☐ It has to be answered │
│ Clicking outside, Escape and │
│ the close button all stop │
│ working while it is open. │
└───────────────────────────────────┘

Dentro de ella, para cada campo: dibuje un marco, establezca Control → Cuadro de texto (o Área de texto para las notas) y enlace Valor a la ruta de estado que edita: state.form.par_name, state.form.par_notes. Un control enlazado a una ruta de estado simple escribe de vuelta en ella, así que no hay nada más que conectar.

Después, el Pulsado del botón Guardar:

if (getState("form").par_name == "") {
notifyError("A case needs a summary.");
} else {
createRecord("par_case", {
par_name: getState("form").par_name,
par_urgent: getState("form").par_urgent,
par_notes: getState("form").par_notes
});
notify("Case created.");
closeEndDrawer();
setState("page", 0);
loadRecords("par_case", "cases", { top: getState("pageSize"), skip: 0,
orderBy: "par_name", countInto: "caseTotal" });
}

Toda escritura termina volviendo a leer la lista. Nada se actualiza por sí solo: la pantalla muestra lo que contiene su estado, y el estado contiene lo que puso ahí la última consulta.

Una pregunta que hay que responder​

Dibuje la confirmación de eliminación de la misma manera, marque Una tarjeta superpuesta y después marque también Hay que responderla. Hacer clic fuera, pulsar Esc y el botón de cerrar dejan de funcionar, así que dibuje su propia salida: un botón Cancelar que ejecute closeModal().

Deje esa segunda marca desactivada en todos los demás casos. Una superposición que alguien abrió por accidente debe cerrarse igual que se abrió; la única que debe negarse es aquella en la que hacer clic al lado no es una respuesta.


10. Guardar, y abrirla de verdad​

Pulse Guardar. Aparecen advertencias en la parte superior si el compilador notó algo: un botón sin palabras, un marco de pantalla que falta, un enlace que no es una expresión pura. Nombran el objeto, así que corríjalas seleccionándolo.

Después salga del diseñador y abra la aplicación desde la lista de aplicaciones del Shell. La vista previa no es lo mismo: representa las mismas pantallas sin ningún entorno detrás, así que lo que no puede mostrarle son sus datos. Todo lo demás —los paneles laterales, las casillas, la barra de herramientas— se comporta igual.


Qué hacer a continuación​

  • Una segunda pantalla. Dibuje otro marco junto al primero, etiquételo como La pantalla y póngale nombre. En cuanto hay dos, aparece un selector Se abre en en la barra de título. navigate("Board") se mueve entre ellas.
  • Pestañas. Una tira de pestañas no es un control: es un campo de estado y un recuadro por valor. Dibuje los recuadros en el mismo rectángulo, enlace el Se muestra de cada uno a state.tab == "notes" y dé a los botones de pestaña un enlace Seleccionado con la misma comparación. Use Dibujar solo en este en la fila de una capa para llegar a un recuadro que está debajo de los demás.
  • Controles que usted no dibujó. El ejemplo studio-component-library incluye una lista desplegable, una búsqueda y un interruptor. Marque Publica componentes en esa aplicación y aparecerán en su paleta; consulte Usar un componente en otra aplicación.
  • Un panel. El mismo lienzo dibuja uno: consulte Poner un panel en una pantalla dibujada.

Solución de problemas​

Lo que veQué es
Only booleans are allowed in this expressionUn campo opcional leído como condición. Envuélvalo: (state.x.par_urgent ?? false).
El enlace de una fila se lee vacíorow solo existe dentro del elemento que lleva Repetir para cada y sus hijos.
Las filas se amontonan unas encima de otrasEl cuadro que rodea la fila repetida necesita diseño automático.
El texto se sale por la parte inferior de un cuadroPóngalo en un marco configurado con Desplazarse hasta él → Hacia abajo, y ancle las palabras a la parte superior.
Una lista desplegable cierra el panel desde el que se abrióCorregido en 0.31. Actualice, o saque el selector del panel.
Guardar está deshabilitadoNada ha cambiado desde el último guardado.