RAP desde cero · Lección 5 de 6
Un semáforo en Fiori con RAP: pinta de colores la valoración de los libros
Colorea en rojo, amarillo o verde la valoración de cada libro con un campo calculado en la CDS y una anotación, y añade estrellas en el detalle. Sin JavaScript.
La lista de libros de la lección 3 muestra la valoración como un número: 4, 5, 3. Funciona, pero hay que leerla. Un semáforo la convierte en algo que se entiende de un vistazo:
| Valoración | Color | Significado |
|---|---|---|
| 0 | gris | Sin valorar |
| 1–2 | rojo | Mala |
| 3 | amarillo | Regular |
| 4–5 | verde | Buena |
Lo mejor: en RAP el semáforo no se programa. No hay JavaScript ni UI5, y tampoco hace falta una clase ABAP. Son tres cambios pequeños, uno por capa:
ZR_LibBook (1) calcula el color: un campo nuevo con CASE
ZC_LibBook (2) lo deja pasar hacia el servicio
MDE (3) le dice a Fiori qué campo pinta con ese color
Al final, como extra, pondremos la valoración en estrellas en la cabecera del detalle.
Antes de empezar: necesitas la biblioteca de las lecciones 2, 3 y 4. La lección 4 hace falta para cambiar la valoración desde la app al probar.
Código guía: el código sigue la sintaxis de ABAP Cloud, pero no se compiló en un sistema SAP para este tutorial. Si algo no activa en tu sistema, el mensaje de ADT indica la línea exacta.
Cómo entiende Fiori los colores
Fiori Elements no sabe de libros ni de valoraciones. Solo entiende un número de criticidad (criticality):
| Valor | Color | Nombre en Fiori |
|---|---|---|
0 |
gris | Neutral |
1 |
rojo | Negative |
2 |
amarillo | Critical |
3 |
verde | Positive |
Así que el trabajo consiste en dos cosas: calcular ese número para cada libro y decirle a Fiori a qué campo se lo aplica.
1. Calcular la criticidad en la Root View Entity
Abre ZR_LibBook y añade un campo calculado justo después de Rating. No existe en la tabla: la base de datos lo calcula al leer, con un CASE.
Extracto de ZR_LibBook (lección 2). Va entre rating as Rating, y @Semantics.amount.currencyCode: 'CurrencyCode'; el resto de la vista no cambia:
rating as Rating,
case
when rating = 0 then 0 -- sin valorar: gris
when rating <= 2 then 1 -- 1 o 2: rojo
when rating = 3 then 2 -- 3: amarillo
else 3 -- 4 o 5: verde
end as RatingCriticality,
Dos detalles:
- El orden de los
whenimporta. Se evalúan de arriba abajo y gana el primero que se cumple. Por esorating = 0va primero: si no, el0caería enrating <= 2y saldría rojo. - Dentro del
CASEse usarating, el nombre de la tabla, noRating, el alias de la vista.
Activa ZR_LibBook (Ctrl+F3) y compruébalo con F8 (Data Preview): aparece la columna RatingCriticality con un 3 o un 2 en cada libro.
2. Dejarlo pasar en la proyección
Un campo que no está en la proyección no viaja por OData. Si no lo añades, la anotación del paso 3 se activa sin errores, pero el semáforo no se pinta. Es el error más típico.
ZC_LibBook completo (el de la lección 3, con la línea nueva RatingCriticality):
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
@EndUserText.label: 'Biblioteca: libros (app)'
@Search.searchable: true
define root view entity ZC_LibBook
provider contract transactional_query
as projection on ZR_LibBook
{
key BookUuid,
@Search.defaultSearchElement: true
BookId,
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.8
Title,
AuthorId,
_Author.Name as AuthorName,
Pages,
Isbn,
Rating,
RatingCriticality,
Price,
CurrencyCode,
LocalLastChangedAt
}
Activa ZC_LibBook.
3. Pintar el campo en la Metadata Extension
Ahora le decimos a Fiori: «la columna Rating se pinta con el color que diga RatingCriticality». Se hace con criticality dentro de lineItem (la lista) y de identification (el detalle).
Extracto de la Metadata Extension de ZC_LibBook (lección 3). Sustituye el bloque de Rating por este y añade debajo el de RatingCriticality:
@UI: { lineItem: [ { position: 60,
criticality: 'RatingCriticality',
criticalityRepresentation: #WITH_ICON } ],
identification: [ { position: 60,
criticality: 'RatingCriticality' } ] }
Rating;
@UI.hidden: true
RatingCriticality;
criticality: 'RatingCriticality'es el nombre del campo que trae el color, entre comillas.criticalityRepresentation: #WITH_ICONañade un icono (✓, ⚠, ✕) junto al número. Así el semáforo se entiende también sin distinguir colores. Si prefieres solo color, usa#WITHOUT_ICON.@UI.hidden: trueocultaRatingCriticality: es un3o un1que solo sirve para pintar, y al usuario no le dice nada.
Activa la Metadata Extension.
4. Pruébalo
- Abre el Service Binding
ZUI_LIB_BOOK_O4, selecciona Book y pulsa Preview. - Pulsa Go. La columna Rating sale en color: Ríos de montaña (5), Aves del sur (4) y Cuentos de invierno (4) en verde, y El último tren (3) en amarillo.
- ¿Y el rojo? Entra en El último tren, pulsa Edit, cambia la valoración a 1 y guarda. Vuelve a la lista: ahora está en rojo.
- Prueba con 0: sale en gris, sin valorar.
Si la vista previa ya estaba abierta, recárgala: Fiori guarda en caché los metadatos del servicio.
Extra: estrellas en la cabecera del detalle
El número en color está bien para la lista. En el detalle de un libro queda mejor con estrellas, como en una tienda online. Fiori lo trae de serie con un Data Point de tipo #RATING.
Hacen falta dos cosas en la misma Metadata Extension:
- Un Data Point sobre
Rating, que dice cómo se dibuja (estrellas, sobre 5). - Un facet de cabecera (
purpose: #HEADER) que lo coloque arriba del detalle.
Un facet es una sección de la página de detalle. El de la lección 3 (id: 'Book') es el cuerpo; este nuevo va en la cabecera. El targetQualifier del facet y el qualifier del Data Point deben coincidir: es lo que los une.
Esta es la Metadata Extension completa, con los cambios de este tutorial (el paso 3 y las estrellas):
@Metadata.layer: #CUSTOMER
@UI.headerInfo: {
typeName: 'Libro',
typeNamePlural: 'Libros',
title: { type: #STANDARD, value: 'Title' },
description: { value: 'AuthorName' }
}
annotate entity ZC_LibBook with
{
@UI.facet: [ {
id: 'HeaderRating',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'Rating',
position: 10
}, {
id: 'Book',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'Libro',
position: 10
} ]
@UI.hidden: true
BookUuid;
@UI: { lineItem: [ { position: 10 } ], identification: [ { position: 10 } ], selectionField: [ { position: 10 } ] }
BookId;
@UI: { lineItem: [ { position: 20 } ], identification: [ { position: 20 } ] }
Title;
@UI: { lineItem: [ { position: 30 } ], identification: [ { position: 30 } ], selectionField: [ { position: 20 } ] }
AuthorId;
@UI: { lineItem: [ { position: 40 } ], identification: [ { position: 40 } ] }
AuthorName;
@UI: { lineItem: [ { position: 50 } ], identification: [ { position: 50 } ] }
Pages;
@UI: { lineItem: [ { position: 60,
criticality: 'RatingCriticality',
criticalityRepresentation: #WITH_ICON } ],
identification: [ { position: 60,
criticality: 'RatingCriticality' } ],
dataPoint: { qualifier: 'Rating',
title: 'Valoración',
visualization: #RATING,
targetValue: 5 } }
Rating;
@UI.hidden: true
RatingCriticality;
@UI: { lineItem: [ { position: 70 } ], identification: [ { position: 70 } ] }
Price;
@UI.hidden: true
LocalLastChangedAt;
}
Activa y recarga la vista previa. Entra en un libro: arriba, junto al título, aparecen sus estrellas. Ríos de montaña tiene las cinco llenas.
Si algo no aparece
| Síntoma | Causa habitual |
|---|---|
| La columna sale sin color | RatingCriticality no está en la proyección ZC_LibBook (paso 2) |
| Todo sale gris | El CASE devuelve siempre 0: revisa que compare rating y el orden de los when |
El 0 sale rojo |
when rating = 0 no es el primero del CASE |
| Aparece una columna con números 1, 2, 3 | Falta @UI.hidden: true en RatingCriticality |
| No salen las estrellas | El targetQualifier del facet no coincide con el qualifier del Data Point ('Rating' en los dos) |
| Nada cambia | La vista previa sigue con los metadatos viejos: recárgala |
Resumen
- Fiori pinta colores a partir de un número de criticidad: 0 gris, 1 rojo, 2 amarillo y 3 verde.
- Ese número se calcula en la CDS con un
CASE, sin ABAP ni JavaScript, y se proyecta para que llegue al servicio. - En la Metadata Extension,
criticalityune el campo visible con su color, y@UI.hiddenesconde el campo auxiliar. - Un Data Point
#RATINGen un facet de cabecera convierte la valoración en estrellas.
El mismo patrón sirve para cualquier estado: pedidos abiertos o cerrados, stock bajo, fechas vencidas. Cambia el CASE y el resto se queda igual.
Recibe los nuevos tutoriales
Un correo cuando publique algo nuevo. Sin spam; te das de baja cuando quieras.
Te enviaré un correo para confirmar la suscripción. Datos tratados según la política de privacidad.