We'll take a step-by-step approach and build up the app over a series of small progressions. We'll start out at nothing, and end up with a fully functioning app.
In the previous part "Preparing", we examined the general characteristics and specific aspects of an enterprise scale app. We also looked into design patterns, and the specific business scenario that we're going to cover. In this part, we're going to build the app.
Let's remind ourselves of what we're aiming for:
The app is made up of a number of moving parts, which are shown in this diagram:
Let's have a quick tour of how the app is put together, visiting each file in turn.
In the beginning the browser loads the web application's index.html which contains only minimal code. It loads the SAPUI5 toolkit core using the standard variant bootstrap script tag, and there is a single function call to instantiate an sap.ui.core.ComponentContainer and place it in the body of the HTML document. The sap.ui.core.ComponentContainer loads an sap.ui.core.UIComponent which is the self-contained encapsulation of the whole application.
The sap.ui.core.UIComponent (henceforth referred to as the 'Component') is defined in the Component.js file in the same folder as index.html; it is found through the specification of resource locations in the bootstrap tag - see the Bootstrap section for more details. The Component has metadata defined, which includes application-level configuration and routing information. Routing is the key best practice navigation mechanism and for non-trivial apps supersedes sap.ui.core.EventBus-based navigation, and even shared-controller-based access to the top-level navigation control (such as an sap.m.NavContainer).
In the initialization part of the Component, models are created and set on the component: the main model that connects to the OData source, and some helper models for internationalization (i18n), where the texts are loaded from a local resource messageBundle.properties, and device detection based arrangement of user interface (UI) controls. Further, the initialization of the sap.ui.core.routing.Router (the Router) is performed. In the main section of the Component the root view ('App') is instantiated. Like all the other views in this sample app, the root view is an XML view.
The root view App, defined in App.view.xml, is very simple and contains a single sap.m.SplitApp control. Neither the master nor the detail pages aggregations are filled at this time in the view definition; this is all managed by the Router, which is also the reason why there's no explicit requirement for a controller connected to this view.
The visible part of the sample app is provided by three main XML views and a fragment. When displayed on devices other than a smartphone, there are two views shown - the master and the detail. Initially this is the Master.view.xml and the Detail.view.xml . Each of these views contain an sap.m.Page. There's also NotFound.view.xml, to be used when no view can be matched to the resource requested. There is also the AddProduct view (AddProduct.view.xml) which is shown in the detail pages aggregation when the add product button is pressed. There are no direct dependencies between views.
In the Detail view there is a couple of sap.ui.layout.form.SimpleForm controls to display the supplier address and category details. These controls are defined separately in XML fragments SupplierAddressForm.fragment.xml and CategoryInfoForm.fragment.xml. They are included in the Detail view using the sap.ui.core.Fragment element. Finally, there's another fragment NameRequiredDialog.fragment.xml, where a Dialog control is defined, to be shown if no name is specified in the new product form.
The Formatter.js file contains formatting utilities that are used in various controls within the Master and Detail views.
The css folder contains style.css which has a very small amount of custom CSS, specifically to position the "not found" message further down that it would normally sit.
The folder structure containing all the resources mentioned in this overview looks like this:
tdg/ | +-- css/ | | | +-- style.css | +-- i18n/ | | | +-- messageBundle.properties | +-- util/ | | | +-- Formatter.js | +-- view/ | | | +-- AddProduct.controller.js | +-- AddProduct.view.xml | +-- App.view.xml | +-- CategoryInfoForm.fragment.xml | +-- Detail.controller.js | +-- Detail.view.xml | +-- Master.controller.js | +-- Master.view.xml | +-- NameRequiredDialog.fragment.xml | +-- NotFound.view.xml | +-- SupplierAddressForm.fragment.xml | +-- Component.js +-- index.html +-- MyRouter.js
So now we have an idea of what our app should consist of, let's start building it.