jueves, 10 de mayo de 2018

Aplicación SAPUI5 para ver un PDF: Creando la app (y III)

En post anteriores, habíamos visto los pasos necesarios para crear un servicio oData en el Gateway que nos devolviese un PDF.

  • En un primer post, habíamos creado un report de ejemplo que nos devolvía un listado ABAP y lo transformábamos en PDF mediante el SPOOL. Era un modo un poco cutre, lo suyo sería crear un Adobe form o un smartform, pero como no era el objetivo del post, lo hicimos en plan rápido.

  • En el segundo post vimos cómo teníamos que crear el proyecto en la SEGW para poder generar el servicio oData que nos devolverá el contenido de un PDF, así como tratar las clases ABAP para devolver el PDF.

Así que ya tenemos preparada la parte de SAP al completo. ¿Qué nos toca ahora? Pelearnos con el SAP Web IDE para crear la aplicación SAPUI5. Será una aplicación de tipo Master-Detail, en la que mostraremos un listado de autores en la parte del Master y un PDF con sus libros en la parte del Detail.

Y el resultado que buscamos será algo como lo siguiente:



Crear la aplicación inicial


Lo primero que tenemos que hacer es crear la aplicación con SAP Web IDE, mediante el uso de una de las plantillas propuestas. En este caso, usaremos una de tipo Master-Detail.

Como siempre, debemos tener en cuenta la versión de la librería SAPUI5 que vamos a usar, para que sea compatible con la librería que tengamos en nuestro SAP front-end.


Le ponemos un nombre al proyecto, uno chulo, con el que aparecerá en nuestro Workspace:


Después elegimos el destination que apunta al sistema SAP y escogemos el servicio oData que creamos en el post anterior.


Y, por último, seleccionamos los atributos básicos: Título que verán los usuarios, el namespace de la aplicación, y la colección que se va a utilizar (en la sección de Data Binding - Object).

No vamos a utilizar ninguna entidad asociada, así que dejamos la sección de Data Binding - List Item vacía.

Ojo, recordemos que la colección Books tiene que estar marcada como Addressable en la SEGW,
porque si no, aquí no nos aparecerá.

Vale, todo esto es sencillito, ya lo habremos hecho un montón de veces. Así que nos podemos crear una configuración y ejecutar la aplicación:

En este ejemplo, la aplicación se ejecutará sobre un Fiori Launchpad

Muy bien, tenemos el esqueleto de la aplicación ya creado: El listado de la sección de Master se obtiene gracias al método BOOKS_GET_ENTITYSET que implementamos en el post anterior. Lo que nos falta por hacer es modificar la parte de la sección Detail para añadir el PDF.

Autorazos, oiga


Añadir el PDF


El PDF lo vamos a mostrar en la vista del detalle, Detail.view.xml. Tenemos que añadir un componente donde podamos incrustar el PDF. Además, en el controlador, Detail.controller.js, añadiremos la lógica para poder generar la url del PDF, que realmente sería <servidor>/<servicio_odata>/Books(entidad)/$value.

Modificando la vista


OJO: Dependiendo de la versión de la librería SAPUI5 que hayamos usado, la vista puede ser distinta a la que se muestra en este post. Pero bueno, todo es tener la idea clara en la cabeza y adaptarla a la versión correspondiente.

Nuestra vista inicial es algo tal que así:


¿Y cómo vamos a añadir el PDF? Pues no vamos a utilizar ningún componente específico para insertar PDFs, ni librerías de terceros. En su lugar, vamos a utilizar un componente SAPUI5 que nos permite integrar código HTML, el sap.ui.core.HTML. Vamos, que lo haremos con código HTML puro y duro, en este caso con las etiquetas <object> y <embed>.

Lo primero que hacemos es limpiar el código generado automáticamente, eliminando el IconTabBar (¡a no ser que queramos usarlo, claro!). En su lugar, insertamos un panel (sap.m.Panel) y, dentro del mismo, el sap.ui.core.HTML. Debemos darle un id a este último para poder usarlo en el controlador.

<Panel id="panPDF">
  <core:HTML id="embPDF" />
</Panel>

En este ejemplo los namespace que usaremos será por defecto para sap.m
y core para sap.uicore

Tocando el controlador


En el controlador vamos a generar el código HTML que integrará el PDF. Pero debemos saber cuándo ejecutar dicho código cada vez que seleccionemos un elemento en el Master.

Descubrir la función que se ejecuta puede depender de la versión de la librería usada. Realmente es sencillo, porque no habrá muchas funciones creadas y por el nombre y el código creado se deducirá rápidamente.

Pero si no nos queda claro, nos vamos al onInit para ver qué función se anexa a la navegación que se realiza cuando seleccionamos un objeto en el Master. Esta función es, en este ejemplo, _onObjectMatched.


En esta función vemos que se llama a la función _bindView, pasándole el path del objeto seleccionado. Este path será algo como Books(Id='LEGUIN')


Esta última función enlaza (bind) la entidad seleccionada con la vista. Cada vez que se invoca, llama a una nueva función, _onBindingChange. ¡Qué mogollón de pasos, caray!


Es ahí donde vamos a añadir nuestro código. Añadimos el código al final de la misma. En este ejemplo, lo he implementado en una nueva función, _setPDFUri, que recibe el path enlazado a la vista.

Habría que limpiar un poco esta función... que parte del código propuesto no nos vale

Vale, ya estamos donde queríamos. En esta función generamos la URL con la que tenemos que invocar el PDF

var sUrl = this.getOwnerComponent().getModel().sServiceUrl;
sUrl = sUrl + sEntityPath + "/$value";

Con esto obtendremos una url similar a <servidor>/sap/opu/odata/sap/mi_servicio/Books(Id='LEGUIN')/$value

Después, recuperamos el objeto SAPUI5 de la vista (this.byId) y le asignamos contenido mediante el método setContent.

¿Qué contenido hay que añadir? Pues HTML puro y duro. Con <object> podemos integrar objetos, como es el caso de PDFs. Pero si queremos asegurar un poco más la compatibilidad con navegadores, dentro del mismo añadimos una etiqueta <embed>, que sólo se visualizará si <object> no es compatible con el navegador. De nuevo, dentro de <embed> podemos añadir más código HTML por si tampoco es compatible.

var embPDF = this.byId("embPDF");
embPDF.setContent('<object data="' + sUrl + '" ... otros atributos html ... >' +
      '<embed src="' + sUrl + '" ... otros atributos html ... >' +
        '<p>Mensaje de incompatibilidad</p>' +
      '</embed></object>');


Con este código, si no ha pasado nada raro, volvemos a ejecutar la aplicación, seleccionamos a un autor y, ¡tachán! Ya tenemos PDF visualizado.


Para finalizar


Lo suyo es que el PDF se vea así, integrado en la aplicación, y eso lo controlábamos en el servicio oData, en el método GET_STREAM, añadiendo a la cabecera el campo Content-Disposition con valor inline, como vimos en el segundo post. Si no nos aparece integrado, deberíamos revisar este método.

Ya sólo nos queda desplegarlo en nuestro front-end, ya sea el propio SAP Cloud Platform o nuestro SAP front-end on-premise.

Código en GitHub


La aplicación está subida a GitHub, tanto la parte SAPUI5 como unos documentos de texto con la parte ABAP, el método DEFINE de la Model Provider Class, y los métodos GET_STREAM y BOOKS_GET_ENTITYSET de la Data Provider Class.

No hay comentarios:

Publicar un comentario