< Anterior | Siguiente >

Lección 8: Adición de variables y funciones al Manejador de UI enriquecida

Añada código fuente que dé soporte a la interfaz de usuario.
En las lecciones 8 y 9, va a actualizar directamente el código fuente de EGL y a revisar los cambios en la pestaña Vista previa.

Adición de código para dar soporte a la cuadrícula de datos

Cambie la declaración de la cuadrícula de datos por dos motivos: para hacer que la página web reaccione cuando el usuario seleccione una célula y para garantizar que la salida de la cuadrícula se haya formateado correctamente.
  1. En el Explorador de proyectos, abra PaymentClient > EGLSource > manejadores y efectúe una doble pulsación en PaymentFileMaintenance.egl.
  2. Pulse en la pestaña Código fuente.

Realice los cambios siguientes, haciendo caso omiso de las marcas de error:

  1. En la declaración allPayments_ui DataGrid, añada el siguiente código inmediatamente antes de la propiedad columns:
    		selectionListeners ::= cellClicked,

    La propiedad selectionListeners especifica una o más funciones que se invocan cuando el usuario selecciona una célula en la cuadrícula. En este caso, el usuario añade un nombre de función a una matriz preexistente. Escribirá la función cellClicked más adelante en esta lección.

  2. Los formateadores son funciones que cambian el aspecto de los valores de las columnas DataGrid. Para mostrar la característica, busque la categoría en la declaración DataGridColumn. Para asegurarse de que el usuario ve una descripción de categoría en lugar de un entero, añada este código tras width=90:
    , formatters = [ formatCategory ]
  3. Cuando obtenga cantidades en euros en una columna, normalmente alineará los valores correctamente. No es necesario una función que realice la alineación correcta. En cambio, añada este código tras la entrada width para cantidades:
    , alignment = DataGridLib.ALIGN_RIGHT
    La declaración allPayments_ui ahora tendrá el aspecto siguientes, con marcas de error para cellClicked y formatCategory:
    allPayments_ui DataGrid {
                   layoutData = new GridLayoutData
                                {row = 2, column = 1,
                                 verticalAlignment = GridLayoutLib.VALIGN_TOP},
                   selectionListeners ::= cellClicked,
                   columns =[
                      new DataGridColumn{name = "category", 
                                         displayName = "Type", 
                                         width = 90,
                                         formatters = [formatCategory]},
                      new DataGridColumn{name = "description", 
                                         displayName = "Description", 
                                         width = 120},
                      new DataGridColumn{name = "amount", 
                                         displayName = "Amount due", 
                                         width = 90,
                                         alignment = DataGridLib.ALIGN_RIGHT}
                   ],
                   data = allPayments as any[],
                   selectionMode = DataGridLib.SINGLE_SELECTION};
  4. Guarde el archivo.

Codificación de la función que responde cuando el usuario pulsa en la cuadrícula de datos

La función cellClicked se invoca cuando el usuario pulsa en una célula de la cuadrícula de datos.

Inmediatamente después de la función start, añada las líneas siguientes:
function cellClicked(myGrid DataGrid in)
   selectedPayment = allPayments_ui.getSelection()[1] as paymentRec;
   selectedPayment_form.publish();
end

Primero, la función cellClicked actualiza el registro selectedPayment con datos de una sola fila de cuadrícula de datos. Esta fila puede incluir más campos que visualizará el usuario. En esta aplicación, la fila única de la cuadrícula de datos procederá de una sola fila de la base de datos.

Segundo, la función publish genera la transferencia de datos del registro selectedPayment al diseño selectedPayment_ui. Esta transferencia la hace posible el código que se ha proporcionado cuando se creó el diseño selectedPayment_ui, que es el diseño de registro único de la parte de la derecha de la página web. Si revisa el código, podrá rastrear las relaciones:
  • Una declaración del Administrador de formularios incluye campos de formulario.
  • Cada campo de formulario hace referencia a una declaración de controlador.
  • La declaración de controlador hace referencia a un modelo en una vista; en este caso, un campo del registro selectedPayment de un hijo del diseño selectedPayment_ui.

El Administrador de formularios proporciona diversas ventajas pero, en esencia, se trata de una recopilación de controladores.

He aquí una explicación de los dos otros problemas: el uso del índice de matriz con corchetes ([1]) y la utilización del operador as:
  • La función getSelection siempre devuelve un subconjunto de filas en la matriz data de la cuadrícula de datos. Sin embargo, cuando se declaró la cuadrícula de datos, se especificó el valor siguiente para indicar que el usuario solamente puede seleccionar una fila cada vez: selectionMode = DataGridLib.SINGLE_SELECTION. Cuando el usuario puede seleccionar solamente una fila, solamente habrá un elemento disponible.
  • Cada elemento de la matriz que ha devuelto una función getSelection será del tipo ANY. Normalmente se utiliza el mismo componenteRegistro para procesar la entrada a la cuadrícula y para procesar la salida de la cuadrícula y, en esta guía de aprendizaje, el componente Registro es paymentRec. El componente Record tiene las utilizaciones siguientes:
    • Para que sea la base de los elementos de matriz que se asignan a la propiedad data de la cuadrícula de datos, tal como se muestra en el valor siguiente:
      data = allPayments as any[]
    • Para realizar conversiones de tipo de datos del elemento de matriz que ha devuelto la función getSelection de la cuadrícula de datos, tal como se muestra a continuación:
      allPayments_ui.getSelection()[1] as paymentRec

    En cada caso, la cláusula as proporciona la conversión de tipo de datos necesaria.

Valores de columna de formato en la cuadrícula

Para añadir la función de formateador:

  1. Añada el código siguiente antes del final de la sentencia end en el archivo:
    function formatCategory(class string, value string, rowData any in)
       value = PaymentLib.getCategoryDesc(value as INT);
    end

    Los formateadores tienen los parámetros que se han mostrado. En este caso, el formateador recorta una función de biblioteca que ha creado anteriormente.

  2. Pulse control-Mayús-O para organizar las sentencias de importación necesarias y guardar el archivo. Desaparecerán todas las marcas de errores.

Prueba de formateo de la cuadrícula de datos y de la transferencia de datos al diseño de registro único

Puede probar los cambios que ha efectuado recientemente incluso antes de acceder a la base de datos.

  1. Pulse la pestaña Vista previa y fíjese que las categorías ahora son descripciones (por ejemplo, “Alquiler” en lugar de “1”).
    La cuadrícula de datos formateada
  2. Pulse en cualquier fila de la cuadrícula de datos y fíjese que el diseño de una sola fila se actualiza como corresponde. Sin embargo, el formateador ha afectado solamente a la cuadrícula de datos, y el campo de descripción del diseño de una sola fila contiene un valor numérico. La guía de aprendizaje le enseñará a corregir este problema más adelante.
  3. Pulse la pestaña Código fuente y cambie la función start de forma que el primer registro de los datos de prototipo incluyan un valor de payeeName, que es un campo de registro paymentRec que no se visualiza mediante la cuadrícula de datos:
    function start()
       allPayments_ui.data =[
          new paymentRec{
             category = 1, description = "test01", amount = 100.00
             , payeeName = "Someone"},
          new paymentRec{category = 2, description = "test02", amount = 200.00},
          new paymentRec{category = 3, description = "test03", amount = 300.00}];
        end
  4. Pulse la pestaña Vista previa y pulse la primera fila de la cuadrícula de datos.
    Los datos se transfieren de la cuadrícula de datos al diseño de registro único
Tal como se muestra, puede conmutar de forma rápida de una pestaña del editor de la UI enriquecida a otra, para probar incluso un pequeño cambio.

Comentario de los datos de prototipo

Puede comentar o descomentar código de forma rápida, tal como se muestra en este paso.
  1. Pulse la pestaña Código fuente.
  2. En la función start, seleccione la sentencia de asignación completa, pulse con el botón derecho del ratón en el área seleccionada y pulse Comentar.
    La selección del código y el elemento de menú Comentario
  3. Las marcas de comentario (//) ahora se hallan al principio de cada línea. Podría eliminar los comentarios repitiendo la tarea y pulsando Descomentar en lugar de Comentar. Sin embargo, deje los comentarios en su lugar. EGL también da soporte a la utilización de los delimitadores barra inclinada con asterisco (/*) y asterisco con barra inclinada (*/), tal como se muestra a continuación:
    /*
     
        Puede añadir comentarios de dos formas distintas.
     
    */

Declaración de una variable de acceso de servicio

Ahora declare una variable de acceso de servicio, que le permitirá comunicarse con el servicio que ha definido anteriormente.

Para crear la variable:

  1. Cerca de la parte superior del código fuente de EGL, busque la declaración del manejador para PaymentFileMaintenance. Añada una línea en blanco e inmediatamente antes de la declaración GridLayout ui, añada la sentencia siguiente:
    dbService SQLService{@dedicatedService};

    La propiedad @dedicatedService indica que el servicio al que se hace referencia es un servicio dedicado, que se desplegará con el manejador de UI enriquecida.

    En la pantalla siguiente, la X roja del margen indica un problema en el código:

    La declaración de la variable de acceso de servicio, en el código

    Par ver el mensaje de error, mueva el cursor por encima de la X.

  2. Corrija el error del “tipo no resuelto” pulsando Control+Mayús+O. La sentencia import nueva proporciona acceso al paquete services, al componente SQLService, que se encuentra en el proyecto PaymentService. La referencia a SQLService se resuelve porque ese proyecto está en la vía de acceso de construcción EGL del proyecto PaymentClient.
  3. Guarde el archivo.

Creación de funciones que utilizan la variable de acceso de servicio para invocar al servicio

Ahora va a crear varias funciones para invocar distintas funciones del servicio dedicado. Cuando comprenda cómo se establece una invocación, las demás le resultarán sencillas.

Comience creando la función que lee todos los datos.

  1. Deje una línea en blanco después de la función cellClicked y añada el código siguiente:
    function readFromTable()
       call dbService.getAllPayments() returning to updateAll
          onException serviceLib.serviceExceptionHandler;
    end
    Nota:
    1. La sentencia call en la UI enriquecida es una variación que solamente se utiliza para acceder a servicios. La comunicación de tiempo de ejecución en este caso es asíncrona, lo que significa que el usuario puede seguir interactuando con el manejador mientras el servicio responda.
    2. La sentencia call asíncrona incluye dos nombres de función:
      • updateAll
      • serviceLib.serviceExceptionHandler

      Los dos son funciones de devolución de llamada, lo que significa que las invoca el código de tiempo de ejecución de EGL cuando responde o falla el servicio. Si el servicio devuelve un valor de forma satisfactoria, se invocará la función updateAll. Si la llamada falla, el código de tiempo de ejecución de EGL invocará una función que esté asociada al nombre serviceLib.serviceExceptionHandler.

      De forma predeterminada, aparecerá un error en la pantalla de información de errores en la vista consola (en el tiempo de desarrollo) o en la parte inferior de la página web (en el tiempo de ejecución). Sin embargo, puede especificar un manejador de errores propio, asignando normalmente un nombre de función en lugar de serviceLib.serviceExceptionHandler.

  2. Pulse en cualquier parte de la sentencia call, pulse con el botón derecho del ratón y pulse Crear funciones Callback. Si lo prefiere, puede pulsar en cualquier lugar de la sentencia, manteniendo pulsada la tecla Control y pulsando 1.
    La opción Crear funciones Callback
    EGL crea una función updateAll vacía. Se debería haber creado un manejador de errores también si hubiera especificado un nombre de función para onException, distinto de serviceLib.serviceExceptionHandler.
    La lista de parámetros de la función updateAll creada equivale al tipo de valor de devolución previsto del servicio. Aquí se hallan las relaciones que explican el comportamiento del editor de la UI enriquecida:
    • La lista de parámetros de la función de devolución de llamada es correcta porque la función getAllPayments del componente Servicio está disponible para el editor.
    • La función está disponible porque ha resuelto la referencia al componente SQLService en un paso anterior.

Ahora, cree la función que añade datos de ejemplo.

  1. Pulse Control-F para acceder al diálogo Buscar y reemplazar, escriba SampleData y pulse Buscar.
  2. Actualice la función sampleData de forma que el código sea el siguiente:
    function sampleData(event Event in)
       call dbService.createDefaultTable() returning to updateAll
          onException serviceLib.serviceExceptionHandler;
    end

    No utilice la característica Crear funciones Callback porque existen funciones de devolución de llamada.

Ahora, cree la función que añade datos.

  1. Actualice la función addRow de forma que el código sea el siguiente:
    function addRow(event Event in)
       call dbService.addPayment(new paymentRec) returning to recordAdded
          onException serviceLib.serviceExceptionHandler;
    end
  2. Pulse en cualquier parte de la sentencia call, pulse con el botón derecho del ratón y pulse Crear funciones Callback. EGL añade la función recordAdded.

Cree la función que suprime datos.

  1. Actualice la función deleteRow de forma que el código sea el siguiente:
    function deleteRow(event Event in)
    
       for(i INT from 1 to allPayments.getSize())
          if(allPayments[i].paymentID == selectedPayment.paymentID)
             allPayments.removeElement(i);
             exit for;
          end
       end
    
       call dbService.deletePayment(selectedPayment) returning to recordRevised
          onException serviceLib.serviceExceptionHandler;
    end
    La función actúa de la forma siguiente:
    • Suprime la fila seleccionada de la matriz de registros locales
    • Invoca al servicio de base de datos para que suprima la fila de la propia base de datos
  2. Pulse en cualquier parte de la sentencia call, pulse con el botón derecho del ratón y pulse Crear funciones Callback. EGL añade la función recordRevised.
  3. Pulse Control-Mayús-F para dar formato al código.
  4. Guarde el archivo.

Actualización de la función de inicio para inicializar la cuadrícula de datos con las filas de la base de datos

Para inicializar la cuadrícula de datos, añada el código siguiente antes de la sentencia end de la función start:

readFromTable();

Aunque haya asignado la función readFromTable directamente a la propiedad onConstructionFunction, se le aconsejará que conserve la función start como unidad de lógica independiente por si más adelante decide añadir otro código que se ejecute antes que se devuelva la página web.

Conserve el código comentado en la función start por si necesita probar la página web sin acceder a la base de datos. Puede utilizar la prestación de comentar y descomentar del editor de UI enriquecida para conmutar de forma rápida de la llamada a función a los datos de prototipo y viceversa.

Cómo completar las funciones de devolución de llamada

Ahora va a completar las funciones de devolución de llamada que se crearon automáticamente:
  • updateAll
  • recordAdded
  • recordRevised

La función updateAll recibe una matriz de registros paymentRec del servicio dedicado. La función se invoca de las formas siguientes:

  1. Actualice la función updateAll de forma que el código sea el siguiente:
    function updateAll(retResult paymentRec[] in)
       allPayments = retResult;
       allPayments_ui.data = allPayments as any[];
    end
    La función actualiza la matriz global de los registros de pagos con los datos recibidos del servicio y, a continuación, renueva la cuadrícula de datos.

La función recordAdded recibe el registro que envió y devolvió la función de servicio addPayment.

  1. Actualice la función recordAdded de forma que el código sea el siguiente:
    function recordAdded(newPayment paymentRec in)
       readFromTable();
    end
    La función readFromTable lee todas las filas de la base de datos. Los datos que ha almacenado la cuadrícula podrán contener luego la fila nueva, incluido el valor paymentID que generó automáticamente la base de datos y que, en cambio, no está disponible en la cuadrícula.

La función recordRevised recibe el registro que envió y devolvió la función de servicio addPayment.

  1. Actualice la función recordRevised de forma que el código sea el siguiente:
    function recordRevised(delPayment paymentRec in)
       allPayments_ui.data = allPayments as any[];
    end
    La función renueva la cuadrícula de datos.
  2. Pulse Control-Mayús-F para dar formato al código. Si detecta errores en el archivo de origen, compare el código con el contenido del archivo en Código para PaymentFileMaintenance.egl después de la lección 8.
  3. Guarde el archivo.

Prueba de la interfaz

Visualice previamente el trabajo ahora que está accediendo a la base de datos.
  1. Pulse la pestaña Vista previa. La cuadrícula de datos no tiene contenido porque se han descomentado los datos de prototipo y la base de datos no tiene filas.
    La cuadrícula de datos iniciales
  2. Pulse Ejemplo para crear datos de ejemplo.
  3. Si EGL solicita una contraseña, escriba admin tanto para el campo ID de usuario como Contraseña. Seleccione Recordar el ID de usuario... y pulse Aceptar.
    La ventana del ID y de la contraseña

    Si sale y reinicia el entorno de trabajo antes de seguir esta guía de aprendizaje, es posible que vuelva a aparecer esta ventana la próxima vez que intente acceder a la base de datos.

    Finalmente, se vuelve a visualizar la cuadrícula con las filas de los datos de ejemplo.
    Se visualizan tres entradas de pago, “Apartment,” “Groceries” e “ISP”
  4. Pulse el botón Añadir. Aparecerá una fila nueva con un único valor predeterminado en la parte inferior de la cuadrícula.
    Se añadirá una fila nueva
  5. Seleccione la fila Apartment y pulse Suprimir. Se suprimirá la fila tanto de la visualización como de la base de datos.
    Ahora habrá desaparecido la fila "Apartment".
  6. Pulse la primera fila de la cuadrícula de datos
    La cuadrícula de datos y el diseño de registro único contienen ambos datos procedentes de la base de datos.
    Los datos procedentes de la base de datos se han transferido desde la cuadrícula de datos al diseño de registro único. Observe que el valor del campo Clave refleja cuántas filas se han añadido a la base de datos y probablemente no coincidan con el valor de la página web.

Punto de comprobación de lección

Ha aprendido a realizar las tareas siguientes:
  • Crear formateadores.
  • Responder a la selección de usuario en una cuadrícula de datos.
  • Transferir datos de la cuadrícula de datos a un diseño de cuadrícula.
  • Comentar y descomentar código.
  • Acceder a servicios desde una aplicación de UI enriquecida.

En la siguiente lección, completará el código para el Manejador de UI enriquecida.

< Anterior | Siguiente >

Comentarios