Skip to content

Latest commit

 

History

History
207 lines (148 loc) · 10.5 KB

README.md

File metadata and controls

207 lines (148 loc) · 10.5 KB

Step 31: Routing with Parameters

We can now navigate between the overview and the detail page, but the actual item that we selected in the overview is not displayed on the detail page yet. A typical use case for our app is to show additional information for the selected item on the detail page.

To make this work, we have to pass over the information which item has been selected to the detail page and show the details for the item there.

 


Preview

The selected invoice details are now shown in the details page

You can access the live preview by clicking on this link: 🔗 Live Preview of Step 31.

To download the solution for this step as a zip file, just choose the link here: 📥 Download Solution for Step 31.


Coding

webapp/manifest.json

We want to hand over the information for the selected item when navigating to the detail view. To achieve that, we add the navigation parameter invoicePath to the detail route in the app descriptor. There, we add a navigation parameter invoicePath to the detail route so that we can hand over the information for the selected item to the detail page.

📝 Note:
Mandatory navigation parameters are defined with curly brackets.

{
  	
    "sap.ui5": {
		
        "routing": {
          "config": {
            "routerClass": "sap.m.routing.Router",
            "type": "View",
            "viewType": "XML",
            "path": "ui5.walkthrough.view",
            "controlId": "app",
            "controlAggregation": "pages"
          },
          "routes": [
            {
              "pattern": "",
              "name": "overview",
              "target": "overview"
            },
            {
              "pattern": "detail/{invoicePath}",
              "name": "detail",
              "target": "detail"
            }
          ],
          "targets": {
            "overview": {
              "id": "overview",
              "name": "Overview"
            },
            "detail": {
              "id": "detail",
              "name": "Detail"
            }
          }
        }
    }
}

webapp/controller/InvoiceList.controller.ts

In the controller for the invoice list view, we extend the onPress event handler in such a way, it not only triggers the navigation to the detail view but also passes the selected item to the routing.

For that we have to pass the event object to our onPress method. This way we get access to the information about the event that occurred. By calling the getSource method we retrieve the source of the event. This method is available for all OpenUI5 events. In our case it will return the ObjectListItem that has been clicked. We use it to pass the information of the clicked item to the detail page so that the same item can be displayed there.

In the navTo method we now add a configuration object to fill the navigation parameter invoicePath with the current information of the item. This will update the URL and navigate to the detail view at the same time. On the detail page, we can access this navigation parameter again and display the corresponding item.

Typically we woudl use the key of the item in the back-end system to identify the selected object, because it is short and precise. For our invoice items however, we do not have a simple key. Therefore we directly use the binding path to keep the example short and simple. The path to the item is part of the binding context which is a helper object of OpenUI5 to manage the binding information for controls. The binding context can be accessed by calling the getBindingContext method with the model name on any bound OpenUI5 control. We need to remove the first / from the binding path by calling .substr(1) on the string because this is a special character in URLs and is not allowed, we need to add it again on the detail page. Also, the binding path might contain special characters which are not allowed in URLs, so we have to encode the path with encodeURIComponent.

import Controller from "sap/ui/core/mvc/Controller";
import JSONModel from "sap/ui/model/json/JSONModel";
import formatter from "../model/formatter";
import { SearchField$SearchEvent } from "sap/m/SearchField";
import Filter from "sap/ui/model/Filter";
import FilterOperator from "sap/ui/model/FilterOperator";
import ListBinding from "sap/ui/model/ListBinding";
import Component from "../Component";
import Event from "sap/ui/base/Event";
import ObjectListItem from "sap/m/ObjectListItem";

/**
 * @namespace ui5.walkthrough.controller
 */
export default class App extends Controller {
    public formatter = formatter;
		
	

    onPress(event: Event): void {
        const item = <ObjectListItem> event.getSource();
        const router = (<Component> this.getOwnerComponent()).getRouter();
        router.navTo("detail", {
            invoicePath: window.encodeURIComponent(item.getBindingContext("invoice").getPath().substr(1))
        });
    }     
};

webapp/controller/Detail.controller.ts (New)

Now we need to create a new detail controller to set the content we passed in with the URL parameter invoicePath on the detail view. This will allow us to access the data of the selected item and display them on the view.

In addition to the (base) controller and our local component we import the Route$PatternMatchedEvent type from sap/ui/core/routing/Route. This event is triggered whenever a route pattern is matched, so we need it to catch any navigation with route pattern "detail/{invoicePath}".

In the onInit method, we receive the router instance from the owner component and attach a listener to the details route's "patternMatched" event by calling the method attachPatternMatched. The onObjectMatched method is the event handler for the "patternMatched" event. When the detail route is matched, it will trigger the onObjectMatched method.

In the onObjectMatched method we bind the view's element to a specific path in the "invoice" model. We get the path from the invoicePath argument from the event that was set in the invoice list controller. Because we have encoded the binding path part in the URL in the invoice list controller, we have to decode it again with decodeURIComponent anf also add the root / in front of the path again that was removed for passing on the path as a URL parameter.

The bindElement function is creating a binding context for a OpenUI5 control and receives the model name as well as the path to an item in a configuration object. This will trigger an update of the UI controls that we connected with fields of the invoice model.

import Controller from "sap/ui/core/mvc/Controller";
import Component from "../Component";
import { Route$PatternMatchedEvent } from "sap/ui/core/routing/Route";

/**
 * @namespace ui5.walkthrough.controller
 */
export default class Detail extends Controller {

    onInit(): void {
        const router = (<Component> this.getOwnerComponent()).getRouter();
        router.getRoute("detail").attachPatternMatched(this.onObjectMatched, this);
    }

    onObjectMatched(event: Route$PatternMatchedEvent): void {
        this.getView().bindElement({
            path: "/" + window.decodeURIComponent( (<any> event.getParameter("arguments")).invoicePath),
            model: "invoice"
        });
    }
};

webapp/view/Detail.view.xml

Our last piece to fit the puzzle together is the detail view. We replace the app controller by the new detail controller that will take care of setting the item's context on the view and bind the properties intro and title of the ObjectHeader to the fields ShipperName and ProductName of our invoice model to display display does two fields of an invoice on the view. We could add more detailed information from the invoice object here, but for simplicity reasons we just display these two fields for now.

<mvc:View
	controllerName="ui5.walkthrough.controller.Detail"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc">
	<Page
		title="{i18n>detailPageTitle}">
		<ObjectHeader
			intro="{invoice>ShipperName}"
			title="{invoice>ProductName}"/>
	</Page>
</mvc:View>

You should now see the invoice details on a separate page when you click on an item in the list of invoices.


Conventions

  • Define the routing configuration in the manifest.json / app descriptor

  • Initialize the router at the end of your Component#init function

 


Next: Step 32: Routing Back and History

Previous: Step 30: Routing and Navigation


Related Information

Routing and Navigation

Tutorial: Navigation and Routing

API Reference: sap.m.routing.Router

Samples: sap.m.routing.Router

API Reference: sap.m.routing.Route

Samples: sap.m.routing.Route