SAP Easy-UI5 App using Northwind OData Service
Crear un FIORI app con el generador EASY-UI5 usando un servicio proporcionado por Northwind en el ambiente de desarrollo local VSCode.
Prerequisitos:
1.- Crear la aplicación FIORI con el generador EASY-UI5.
Abrir una sesión command de Windows e instalar el generador.
npm install -g yo generator-easy-ui5
Crear un directorio de proyecto e invocar el generador Yeoman.
yo easy-ui5 project
Responder los parámetros del generador.
Abrir el proyecto en Visual Studio Code.
code tutorial.products
Reemplazar el contenido del archivo i18n en uimodule/webapp/i18n/i18n_en.properties.
title=Coming soon!
appTitle=Product List
appDescription=App Description
Revisar el proyecto hasta el momento.
npm start
2.- Agregar una vista a la aplicación.
Añadir una vista que despliegue una lista de productos. Abrir una terminal y ejecutar:
yo easy-ui5 project newview
Eliminar valor del pattern en el archivo uimodule/webapp/manifest.json
Eliminar el contenido del tag <App> en el archivo webapp/view/Mainview.view.xml
Reemplazar el contenido del tag <App> en el archivo webapp/view/Products.view.xml.
3.- Agregar la fuente de datos.
Para completar la lista con elementos, vincule una fuente de datos a la aplicación. Para ello, existe otro subgenerador:
yo easy-ui5 project newmodel
Modificar en el archivo uimodule/webapp/xsapp.json el destination.
{
"welcomeFile": "/flpSandbox.html",
"routes": [
{
"source": "^/V2/(.*)$",
"authenticationType": "none",
"destination": "Northwind",
"csrfProtection": false
},
{
"source": "^(.*)",
"target": "$1",
"authenticationType": "xsuaa",
"service": "html5-apps-repo-rt"
}
]
}
Modificar en el archivo uimodule/ui5.yaml el array de destination.
destinations:
- name: "Northwind"
url: "https://services.odata.org/"
Cancelar la ejecución anterior con ctrl+ c y volver a ejecutar la aplicación para ver los cambios.
npm start
4.- Agregar una vista de detalle de la aplicación.
Añadir una vista que despliegue el detalle del producto. Abrir una terminal y ejecutar:
yo easy-ui5 project newview
Ajustar el valor del pattern en el archivo uimodule/webapp/manifest.json
{
"name": "ProductDetail",
"pattern": "Product/{productId}",
"target": [
"TargetProductDetail"
]
}
Cambiar el tipo de lista y el evento listener en el archivo uimodule/webapp/view/Products.view.xml
Añadir lógica de navegación en el archivo uimodule/webapp/controller/Products.controller.js
sap.ui.define([
"tutorial/products/controller/BaseController"
], function (Controller) {
"use strict";
return Controller.extend("tutorial.products.controller.Products", {
handleListItemPress: function (oEvent) {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
var selectedProductId = oEvent.getSource().getBindingContext().getProperty("ProductID");
oRouter.navTo("ProductDetail", {
productId: selectedProductId
});
}
});
});
Añadir lógica al detalle en el archivo uimodule/webapp/controller/ProductDetail.controller.js
sap.ui.define([
"tutorial/products/controller/BaseController"
], function(Controller) {
"use strict";
return Controller.extend("tutorial.products.controller.ProductDetail", {
onInit: function () {
const oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("ProductDetail").attachMatched(this._onRouteMatched, this);
},
_onRouteMatched: function (oEvent) {
const iProductId = oEvent.getParameter("arguments").productId;
const oView = this.getView();
oView.bindElement({
path: "/Products(" + iProductId + ")",
events: {
dataRequested: function () {
oView.setBusy(true);
},
dataReceived: function () {
oView.setBusy(false);
}
}
});
},
});
});
Añadir declaraciones requeridas al archivo uimodule/webapp/view/ProductDetail.view.xml
Cancelar la ejecución anterior con ctrl+ c y volver a ejecutar la aplicación para ver los cambios.
npm start
4.- Enriquecer la página de lista de productos.
Añadir smart controls en el archivo uimodule/webapp/view/Products.view.xml
Añadir smart controls en el archivo uimodule/webapp/view/ProductDetail.view.xml
Reemplazar Header de la vista en el archivo uimodule/webapp/controller/ProductDetail.controller.js
sap.ui.define([
"tutorial/products/controller/BaseController",
"sap/m/MessageToast"
], function (Controller, MessageToast) {
"use strict";
Y el siguiente código después de método _onRouteMatched
addToCart: function () {
MessageToast.show("Added to cart");
},
markAsFav: function (evt) {
const oButton = evt.getSource();
if (oButton.getIcon() === "sap-icon://unfavorite") {
oButton.setIcon("sap-icon://favorite");
MessageToast.show("Added to favorites");
return;
}
oButton.setIcon("sap-icon://unfavorite");
MessageToast.show("Removed from favorites");
},
Añadir secciones al detalle. Insertar el código después del tag </uxap:headerContent> en la vista.
Actualizar la definición de datos, para mostrar proveedores y categorías, en el método del controlador de la página de detalle de producto: uimodule/webapp/controller/ProductDetail.controller.js.
_onRouteMatched: function (oEvent) {
const iProductId = oEvent.getParameter("arguments").productId;
const oView = this.getView();
oView.bindElement({
path: "/Products(" + iProductId + ")",
parameters: {
expand: "Supplier,Category"
},
events: {
dataRequested: function () {
oView.setBusy(true);
},
dataReceived: function () {
oView.setBusy(false);
}
}
});
},
Añadir el siguiente código después del método markAsFav para mostrar la foto del producto.
trimSuperfluousBytes: function (sVal)
if (typeof sVal === "string") {
const sTrimmed = sVal.substr(104);
return "data:image/bmp;base64," + sTrimmed;
}
return sVal;
},
5.- Añadir información de Jerarquía.
Añadir el siguiente método al archivo uimodule/webapp/controller/BaseController.js después del método onNavBack para utilizar la utilidad de jerarquía del Shellbar.
addHistoryEntry: (function() {
let aHistoryEntries = [];
return function(oEntry, bReset) {
if (bReset) {
aHistoryEntries = [];
}
var bInHistory = aHistoryEntries.some(function(oHistoryEntry) {
return oHistoryEntry.intent === oEntry.intent;
});
if (!bInHistory) {
aHistoryEntries.unshift(oEntry);
this.getOwnerComponent().getService("ShellUIService").then(function(oService) {
oService.setHierarchy(aHistoryEntries);
});
}
};
})(),
En el archivo uimodule/webapp/manifest.json añadir una nueva configuración a la propiedad sap.ui5 después de sección models.
{
"sap.app": {},
"sap.ui": {},
"sap.ui5": {
"models": {},
"services": {
"ShellUIService": {
"factoryName": "sap.ushell.ui5service.ShellUIService",
"lazy": false,
"settings": {
"setTitle": "auto"
}
}
},
}
}
En el archivo uimodule/webapp/controller/Products.controller.js añadir una nuevo item en el controlador en la vista de la lista después de la función handleListItemPress.
onInit : function () {
this.addHistoryEntry({
title: "All Products",
icon: "sap-icon://product",
intent: "#display-uimodule"
}, true);
},
En el archivo uimodule/webapp/controller/ProductDetail.controller.js añadir una nuevo item en el controlador en la vista de detalle, cambiar el dataReceived dentro del método _onRouteMatched.
_onRouteMatched: function (oEvent) {
const iProductId = oEvent.getParameter("arguments").productId;
const oView = this.getView();
oView.bindElement({
path: "/Products(" + iProductId + ")",
parameters: {
expand: "Supplier,Category"
},
events: {
dataRequested: function () {
oView.setBusy(true);
},
dataReceived: function () {
oView.setBusy(false);
this.addHistoryEntry({
title: "Product - " + oView.getBindingContext().getProperty("ProductName"),
icon: "sap-icon://product",
intent: "#display-uimodule&/Product/" + iProductId
});
}.bind(this)
}
});
},
6.- Probar la aplicación.
Cancelar la ejecución anterior con ctrl+ c y volver a ejecutar la aplicación para ver los cambios.
npm start
Lista de productos.
Detalle de productos.
7.- Build and Deploy.
En la terminal ejecutar el siguiente comando para crear el archivo MTA.
npm run build:mta
Con este otro comando hacemos el deploy del proyecto.
cf deploy mta_archives/products_0.0.1.mtar
Finalmente consultamos el Link de la aplicación con el comando:
cf html5-list -di products_destination -u --runtime launchpad
Lesson learned:
Creo que es un generador para un programador avanzado que requiere empezar rápidamente el desarrollo. A diferencia de otros tutoriales la entrega final es muy completa, casi para usuario final.
FIN.