Search code examples
sapui5

Routing with parameters does not work


I am following the tutorial here and I got stuck on routing with parameters.

The example app did not run on my local use, I therefore change it to make use of local data. However, I get the error "Uncaught Error: Invalid value "Invoices/1" for segment "{invoicePath}"" when I click on an element in the invoices list. It should open up a new Detail page and display the product name and the amount.

Here is my routing manifest:

"routing": {
      "config": {
        "routerClass": "sap.m.routing.Router",
        "viewType": "XML",
        "viewPath": "sap.ui.demo.wt.view",
        "controlId": "app",
        "controlAggregation": "pages"
      },
      "routes": [
        {
          "pattern": "",
          "name": "overview",
          "target": "overview"
        },
        {
          "pattern": "detail/{invoicePath}",
          "name": "detail",
          "target": "detail"
        }
      ],
      "targets": {
        "overview": {
          "viewName": "Overview"
        },
        "detail": {
          "viewName": "Detail"
        }
      }
    }

Invoices.json example data:

{
  "Invoices": [
    {
      "ProductName": "Pineapple",
      "Quantity": 21,
      "ExtendedPrice": 87.2000,
      "ShipperName": "Fun Inc.",
      "ShippedDate": "2015-04-01T00:00:00",
      "Status": "A"
    }
  ]
}

InvoiceList.controller.js. Where I populate the Invoices list and call the view change.

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/ui/model/json/JSONModel",
    "sap/ui/demo/wt/model/formatter",
    "sap/ui/model/Filter",
    "sap/ui/model/FilterOperator"
], function (Controller, JSONModel, formatter, Filter, FilterOperator) {
    "use strict";

    return Controller.extend("sap.ui.demo.wt.controller.InvoiceList", {

        onPress: function (oEvent) {
            var oItem = oEvent.getSource();
            var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
            oRouter.navTo("detail", {
                invoicePath: oItem.getBindingContext("invoice").getPath().substr(1)
            });
        }
    });

});

Solution

  • The error message is raised by the the router library. The route is defined as detail/{invoicePath} and you pass Invoice/1 as parameter, which is not allowed as the parameter contains the slash which is considered as URL segment separator.

    However, you mentioned that you could not run the example locally and did some adoptions. The path looks like you are using a JSONModel now. This means you need to adopt several parts in your example as well.

    InvoiceList controller:

    oItem.getBindingContext("invoice").getPath().substr(10)
    

    The binding context should be /Invoices/1 and you want to pass the only the index. Therefore you need to cut off /Invoices/.

    Detail controller:

    _onObjectMatched: function (oEvent) {
        this.getView().bindElement({
            path: "/Invoices/"+ oEvent.getParameter("arguments").invoicePath,
            model: "invoice"
        });
    }
    

    This will bind your view to /Invoices/1 in the corresponding model.