Routing en SAPUI5: navegación con URL, no con setVisible
Rutas, patrones y parámetros en el manifest, y un router que sincroniza el hash con la vista. Cómo pasar de una lista a un detalle sin ocultar controles a mano, con navegación de regreso que respeta el historial.
Por Logali Tech 3 min de lectura
La navegación casera en UI5 tiene un olor característico: un montón de setVisible(true) y setVisible(false) para ocultar y mostrar páginas. Funciona hasta que el usuario pulsa Atrás en el navegador, o comparte un enlace, o recarga. El router de UI5 resuelve exactamente eso: vincula el hash de la URL a una vista, y la navegación se vuelve declarativa.
El modelo mental: hash, ruta y target
- Ruta (
route): un patrón de URL.""es la home;details/{invoicePath}captura un parámetro. - Target: la vista que se muestra cuando esa ruta coincide.
- Router: el objeto que escucha el hash y monta el target correcto.
Lo declaras todo en el manifest.json, y el componente solo lo inicializa.
flowchart TB URL["URL hash details/xyz"] --> RT["Router escucha el hash"] RT --> M["Ruta que coincide patrón: details/[path]"] M --> TG["Target Details.view.xml"] TG --> V["Vista montada con su binding"]
Declarar rutas en el descriptor
Dos rutas: la vista general en la raíz y el detalle con un parámetro en el patrón.
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"controlId": "app",
"controlAggregation": "pages",
"async": true
},
"routes": [
{ "name": "RouteApp", "pattern": "", "target": ["TargetOverview"] },
{ "name": "Details", "pattern": "details/{invoicePath}", "target": ["TargetDetails"] }
],
"targets": {
"TargetOverview": { "viewName": "Overview", "viewId": "Overview" },
"TargetDetails": { "viewName": "Details", "viewId": "Details" }
}
}
El componente arranca el router en su init, una sola línea:
this.getRouter().initialize();
Navegar con un parámetro
Desde la lista, al pulsar un ítem, pides al router que vaya a Details pasando el path del contexto vinculado. Nada de estado global: la URL lleva la información.
navigateToDetails: function (oEvent) {
var oItem = oEvent.getSource();
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("Details", {
invoicePath: window.encodeURIComponent(
oItem.getBindingContext("northwind").getPath().substr(1)
)
});
}
Y en el detalle, escuchas el patternMatched para vincular la vista al objeto que llega en la URL. La vista se rellena sola por binding.
onInit: function () {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("Details").attachPatternMatched(this._onObjectMatch, this);
},
_onObjectMatch: function (oEvent) {
this.getView().bindElement({
path: "/" + window.decodeURIComponent(oEvent.getParameter("arguments").invoicePath),
model: "northwind"
});
}
La navegación de regreso que no rompe el navegador
Aquí está la diferencia entre una app amateur y una profesional. No hagas navTo a la home sin más: consulta el historial. Si el usuario llegó desde dentro de la app, history.go(-1) respeta su recorrido; si entró por enlace directo, entonces sí navegas a la raíz.
onNavBack: function () {
var oHistory = History.getInstance();
if (oHistory.getPreviousHash() !== undefined) {
window.history.go(-1);
} else {
UIComponent.getRouterFor(this).navTo("RouteApp", {}, true);
}
}
Cuando la navegación vive en la URL, el botón Atrás del navegador, los enlaces compartidos y el deep linking funcionan gratis. Cuando vive en
setVisible, no funciona ninguno.
Regla práctica: si tu app tiene más de una pantalla, no hay excusa para no usar el router. El coste de declarar dos rutas en el manifest es de cinco minutos; el coste de no hacerlo es cada bug de navegación que aparezca después.
Con esto cerramos la parte de arquitectura, binding y navegación. En el último post de esta serie entramos en TypeScript en SAPUI5: tipos reales en vez de JSDoc simulado, eventos tipados y errores que el compilador te enseña antes del deploy.
¿Te ha resultado útil?
Gracias por tu valoración.
Comentarios
Aún no hay comentarios.