miércoles, 12 de julio de 2017

SAPUI5: Crear una tabla (II, tabla enlazada con servicio oData)

En un post anterior, estuvimos viendo cómo funcionan las tablas con un ejemplo sencillo, mostrando datos estáticos. Pero claro, eso no nos vale para mucho. Lo que queremos hacer es mostrar los datos de un servicio oData, obteniendo así una tabla dinámica megachula.

Y eso es lo que vamos a hacer ahora. Partiendo de la aplicación del otro día, añadiremos una tabla que consulte la colección Employees del servicio de Northwind.

Los pasos que vamos a seguir son:

  • Modificar la aplicación para cargar el servicio oData. Esto no tiene que ver con tablas, pero nos toca hacerlo.
  • Crearemos una tabla que cargue los datos de la colección Employees.
  • Modificaremos la tabla para darle formato y que quede más guapetona.

Cargar el servicio oData en la aplicación


Para poder usar el servicio oData, podríamos crear una nueva aplicación a partir de una plantilla del Web IDE y copiar el código que ya habíamos hecho. Pero vamos a aprovechar lo que ya teníamos y añadir el servicio manualmente. Eso sí, tenemos que habernos definido un destination que apunte al servicio de Northwind.


Si la aplicación la hicimos con la versión 1.30 o superior de SAP UI5, los modelos se definen el archivo manifest.json (el descriptor), y la aplicación los instancia automáticamente. Podemos ver los cambios necesarios en este documento de ayuda.

Vamos a hacer los cambios en el manifest.json mediante la vista Descriptor Editor para hacerlo más sencillo. Abrimos el manifest.json en este modo (lo podemos cambiar en la parte inferior) y vamos a la pestaña Data Sources. Ahí creamos una nueva entrada para elegir nuestro servicio de Northwind (pulsamos el + y elegimos el servicio como hacíamos en la sección Data Connection de este post).





Después, en la sección Models, añadimos una nueva entrada pulsando también el botón +.



Ahí escogemos la fuente de datos creada antes y lo marcamos como modelo por defecto (¡el modelo sin nombre!).


Con estos pasos nuestra aplicación instanciará el modelo por defecto usando como fuente el servicio oData de Northwind.


Crear la tabla de forma sencillota



En el fichero Tabla.view.xml nos creamos una tabla, recordando lo que habíamos visto de los agregados items y columns.

Os recuerdo que estamos usando la abreviatura xmlns="sap.m", por eso donde ponga <Table> realmente es como si dijésemos <sap.m.Table>.


Definir la colección


Lo primero, es indicar qué colección vamos a cargar en la tabla. Eso lo hacemos usando el atributo items dentro de la etiqueta de la tabla:

<Table items="{nombre_del_modelo>/Coleccion}">

Como el modelo que estamos usando es el por defecto (sin nombre) y la colección es Employees, ponemos lo siguiente:

<Table items="{/Employees}">

Ojo, que en la tabla vamos a tener realmente dos "secciones" llamadas items: El atributo (lo que acabamos de definir ahora mismo), que nos indica la colección a usar, y el agregado (lo que viene entre la etiqueta <items></items>), que veremos al Definir las filas.

Definir las columnas


Después definimos las columnas que vamos a mostrar. Serán seis: Apellido, Nombre, ID, Título, Nacimiento y Contratación. Esto lo hacíamos en el agregado <columns>.

Definir las filas


Y en el agregado items... tachán tachán... ¡sólo creamos una línea!

En este caso, lo que estamos haciendo en items es definir una especie de plantilla, que se repetirá una vez por cada registro de la colección Employees.

<Table items="{/Employees}">
  <columns>aquí las columnas</columns>
  <items>
    <ColumnListItem>
      <cells>aquí las celdas de la plantilla</cells>
    </ColumnsListItem>
  </items>
</Table>

Vale, pues vamos a definir la plantilla. Tenemos que saber las propiedades de la colección que mostraremos en la tabla. Cada propiedad la mostraremos entre llaves, en plan:

<Text text="{NombrePropiedad}">

Podemos añadir textos fijos si queremos, sin meterlos entre llaves (<Text text="el valor es {NombrePropiedad}">), pero no nos vamos a complicar.

¿Cómo sabemos las propiedades que queremos mostrar? Venga, a visitar la entidad Employee en el metadata:


Con toda esta información ya podemos definir "la plantilla" de las filas, y el todo nos queda así:

Tanto blablabla para luego este poquito de código

Pues si ejecutamos la aplicación y todo ha ido bien, tendremos el resultado que buscábamos.

Aquí vemos dos tablas, la primera era la estática del post anterior y la segunda es la dinámica.


Darle un poquito de color a la tabla


Vamos a dejar la tabla un pelín más bonita. Sólo para ver alguna cosa que podemos hacer.

Os pongo el código a continuación y vamos comentando los cambios hechos:

Sombra aquí y sombra allá, maquíllate, maquíllate...


Lo primero que hacemos es ordenar la tabla por el apellido (LastName). Eso lo conseguimos cambiando el atributo items, con este formato:

<Table items="{ path: '/NombreColeccion',
                            sorter: { path: 'NombreDeLaPropiedadParaOrdenar',
                                          descending: false
                                        }
                           }/>
                         
Además, para evitar que la tabla cargue demasiados datos (sobre todo cuando usamos un dispositivo móvil), podemos usar el atributo growing, que nos permite definir cuantas filas va a cargar la tabla, independientemente de que la colección tenga más. Las opciones que he puesto en el ejemplo son:


  • growing = true para activar esta propiedad
  • growingThreshold=5 para mostrar sólo 5 filas. Si no se indica este atributo, por defecto muestra 100.
  • growingScrollToLoad=true para que, cuando hagamos scroll al final de la tabla, cargue más entradas (otras 5 en nuestro caso).


También añadimos un título a la tabla, gracias a headerToolbar.

Por último, las fechas mostradas por defecto quedan un poco feunas, así que le damos un formato para que se vean más cortitas. Hay varias opciones que podemos ver aquí, yo he elegido un formato medio (por ejemplo, 11 jul. 2017).

Eso lo conseguimos con este formato:

<Text text="{ path: 'NombreDeLaPropiedad',
  type: 'sap.ui.model.type.Date',
  formatOptions: { style: 'medium' } }"/>

Con estos cambios, nos queda la siguiente tabla:


Por defecto sólo me salen 5 filas. Pero si bajo con el scroll, cargará otras cinco más.
En la imagen se ve como la aplicación se lo está pensando. 


Y para finalizar


Para finalizar, vamos a hacer unos ajustes adicionales para que la tabla se adapte al tamaño del dispositivo. Pero esto lo veremos en el siguiente post.




4 comentarios:

  1. Muy buen artículo, como siempre. Te sigo desde hace tiempo pero hoy es la primera vez que me voy a atrever a hacerte una pregunta. Es algo que mis compañeros y yo llevamos tiempo dándole vueltas y no sabemos resolver. Es para alguien verdaderamente experto en el Gateway que une SAPUI5 y los módulos de función ABAP. Allá va:

    ¿sabrías como hacer llegar los parámetros $top, $skip y $count de una llamada OData a las funciones ABAP? Tenemos un problema, y es que cuando llamamos a una función ABAP que devuelve un listado no podemos pasarle los parámetros de paginación (skip y top), por lo que la función en ABAP siempre tiene que devolver todos los registros (si son 10.000 pues los 10.000). No nos pasa lo mismo con el $filter, que si se lo podemos pasar y gracias a eso realizamos el filtrado. Es en el Gateway donde se aplica el skip y el top y nos los devuelven a la aplicación SAPUI5 ya paginado. Sin embargo, como en ABAP si que se realiza todo el esfuerzo de devolver los 10.000 registros, pues tarda muchísimo. Parece que el único parámetro OData capaz de recibir ABAP es el $filter, que es donde vienen todos los campos.

    La solución más sencilla sería añadir a cada entidad OData dos parámetros más que hagan la función del $top y el $skip, pero eso lo vemos una chapuza y no queremos hacerlo. ¿Tu sabrías como se puede hacer?

    Un saludo y felicidades por tu blog.

    ResponderEliminar
    Respuestas
    1. Hola,

      ¿Habéis probado usando el parámetro io_tech_request_context del get_entityset? Mira en este ejemplo y busca io_tech_request_context->get_top() a ver si hay suerte y os vale.

      https://help.sap.com/saphelp_nw74/helpdata/en/30/116c10d4ff42908d4a4ad023b77634/frameset.htm

      Eliminar
  2. Hola una consulta estaba repasando a ver si daba con la respuesta, como le puedo pasar a mi odata un parametro que ingrese desde la aplicacion, por ejemplo supongamos que le digo al usuario que ingrese un material para buscar ese material en la mara y que me devuelva el resultado en una lista o tabla

    Seria algo tipo https://:/...//Products?$filter=Materials eq 'IDMATERIAL'

    este filtro donde lo programaria en abap ? a parte de marcarle el check de filter. Si tienes un ejemplo bajo manga te lo agradeceria esta y la otra vida jaja

    ResponderEliminar
    Respuestas
    1. Mira este post, aunque creo que llego tarde con la respuesta
      https://uxsap.blogspot.com.es/2017/03/sapui5-y-filtros.html

      Eliminar