Professional Documents
Culture Documents
The Model View Controller
The Model View Controller
This page describes the concepts and the usage of MVC in SAPUI5 and especially the role of the artifacts View and Controller. For detailed information on the Model appraoch and the available Model flavors, goto Data Binding in Applications
Introduction
SAPUI5 offers Views and Controllers in the form of single files, these are
sap.ui.core.mvc.View
Objectives
Provide support for MVC paradigm Support development in distributed teams with different source locations Suggest file structure, naming, and usage patterns Add capability of UI declaration (in comparison to a programmatic construction)
Usage
According to the MVC paradigm, the View is responsible for defining and rendering the UI, the Model manages the application data, and the Controller reacts to View events and user interaction by modifying View and Model. This pattern defines a useful separation of concerns which helps developing or changing parts independently. Views and Controllers often form a 1:1 relationship; alternatively it is also possible to have UI-less Controllers (also named application controllers) and Views without Controllers. Since a View is a SAPUI5 Control from the technical point of view, it can have or inherit a SAPUI5 Model. Note that View and Controller represent reusable units, and distributed development is highly supported (developer of artifact is not the same person as the developer who is (re-)using it).
machine where the SAPUI5 runtime was loaded. Therefore you have to inform the runtime that your Views and Controllers are located on your local machine:
jQuery.sap.registerModulePath(sModuleNamePrefix, sURL);
or
sap.ui.localResources(sModuleNamePrefix);
In most cases it will be sufficient to use sap.ui.localResources which internally registers
sModuleNamePrefix to the URL "./" + sTransformedModuleNamePrefix where the transformed name has all dots replaced by slashes. All files starting with sModuleNamePrefix will
then be loaded relatively to the location of the HTML page that was calling sap.ui.localResources. If your files are located at " http://<localhost:8080>/<myapp>/", for example, you can use registerModulePath as follows:
jQuery.sap.registerModulePath("myapp", "http://<localhost:8080>/<myapp>/");
or
sap.ui.localResources("myapp");
All Views and Controllers having a name starting with myapp, for example myapp.MyView, will now be loaded from your local machine.
Controller Definition
You define a simple Controller, having no function yet, as following:
Controller Functions
There are predefined lifecycle hooks you can implement. Typically you also add event handlers or other functions. Controllers can fire events that other Controllers or entities can register for.
Lifecycle Hooks
The lifecycle hooks are as following:
onInit() - Called when a View is instantiated and its controls (if available) are already
created. Can be used to modify the View before it is displayed to bind event handlers and do other one-time initialization.
onExit() - Called when the View is destroyed. Use this one to free resources and finalize
activities.
onAfterRendering() - Called when the View has been rendered (therefore its HTML is
part of the document). Post-rendering manipulations of the HTML can be done here. This hook is the same one that SAPUI5 controls get after being rendered. onBeforeRendering() - Is invoked before the Controller's View is re-rendered (and NOT before the first rendering). You would use onInit() in the case that the hook shall be invoked before the first rendering.
View Types
While the XML and JSON notation for SAPUI5 UI controls has been introduced, the MVC pattern shall also be supported in the case that a traditional programmatic UI construction is preferred.
XMLView o UI is defined in an XML file/string JSONView o UI is defined via JSON in a file/string JSView
Note that the XMLView type is constructed in a way that a mix with plain HTML is possible.
While the View types mentioned above are predefined and offered to be chosen as View option in the application creation wizard - in the case that the tools are used for Web application development - others can also be plugged in.
JSView Definition
A JavaScript View is created like a Controller. The suffix for such a file is .view.js. There are two default methods that can be implemented and that would usually always be used:
getControllerName() - Specifies the Controller belonging to this View. In the case that
it is not implemented, or that "null" is returned, this View does not have a Controller. createContent() - Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed. Since the Controller is given to this method, its event handlers can be attached right away.
Example:
createContent: function(oController) { var oButton = new sap.ui.commons.Button({text:"Hello JS View"}); oButton.attachPress(oController.handleButtonClicked); return oButton; } });
The string in quotes is the View name, which again equals the SAPUI5 module name within the require/declare concept.
XMLView Definition
This type of View is defined in an XML file, and the file name has to end with .view.xml, or as an XML string. The View name along with the folder structure above is the name of the View. This name again equals the SAPUI5 module name within the require/declare concept. Example: In the case of resources/sap/hcm/Address.view.xml, the View name would be
sap.hcm.Address. This View name is used when the application displays an instance of this View.
If you define the XMLView via an XML string, no file or require/declare is needed. The file looks like this:
Namespaces in XMLViews
Analoguous to generic XML mapping features, the names of the SAPUI5 control libraries are mapped to XML namespaces. You can choose any of the required namespaces to be the default namespace, therefore the respective control tags do not need a prefix. The surrounding <View> tag is always required and in this case has the core namespace defined in the first line. Of course you can give any name; to keep the tag names shorter it might be useful for example to use "c" instead of "core". Note: If controls are located in a subpackage of a control library, as it is the case for the sap.ui.commons.layout.MatrixLayout, they need to have their own XML namespace:
<core:View controllerName="sap.hcm.Address" xmlns="sap.ui.commons" xmlns:core="sap.ui.core"> <Panel> <content> <!-- this is the general way of adding children: use the aggregation name --> <Image src="http://www.sap.com/global/ui/images/global/saplogo.png"/> <Button text="Press Me"/> </content> </Panel> <core:View>
MY_TEXT=Hello World
Example:
<core:View resourceBundleName="myBundle" resourceBundleAlias="i18n" controllerName="sap.hcm.Address" xmlns="sap.ui.commons" xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml"> <Panel> <Button text="{i18n>MY_TEXT}"/> </Panel> <core:View>
The necessary ResourceModel for binding these texts is created during View instantiation. The Model will be set as secondary Model with the given alias to the View instance. If you want to bind other properties to another Model you have to create the Model on your own within the corresponding Controller, or HTML page, and attach it to the View with another alias. The binding itself behaves like every SAPUI5 databinding and like described above.
3. The XHTML nodes are converted 1:1 to HTML, the XMLView does not deal with any differences between XHTML and HTML (for example re-writing auto-closing tags) 4. The created HTML DOM nodes are preserved during re-rendering of an XMLView: Modifications to the DOM are not lost. Further restrictions are currently not known. Note: As an alternative to embedding XHTML, you can use the sap.ui.core.HTML control. Note that it is less convenient since encoding of the content is required. To mix SAPUI5 controls freely with native XHTML, you simply need another namespace - the XHTML one - and then you can use (X)HTML:
<core:View controllerName="sap.hcm.Address" xmlns="sap.ui.commons" xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml"> <Panel> <Button text="Press Me. I am a SAPUI5 Button"/> <html:button>No, press me. I am native HTML Button.</html:button> </Panel> <core:View>
<core:View controllerName="sap.hcm.Address" xmlns="sap.ui.commons" xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml"> <html:style> .mySuperRedButton { color: red; } </html:style> <Panel> <Button class="mySuperRedButton" text="Press Me"/> </Panel> <core:View>
It is recommended to carefully choose the elements that you style since the CSS always affects the whole page and is NOT restricted to the View.
JSONView Definition
This type of View is defined in a file and that file's name must end with .view.json, or as a JSON string. The View name along with the folder structure above is the name of the View. This name again equals the SAPUI5 module name within the require/declare concept. For example, the file could be resources/sap/hcm/Address.view.json, then the View name would be sap.hcm.Address. This View name is used when the application wants to display an instance of this View.
{ "Type":"sap.ui.core.mvc.JSONView", "controllerName":"sap.hcm.Address", "content": [{ "Type":"sap.ui.commons.Image", "id":"MyImage", "src":"http://www.sap.com/global/ui/images/global/sap-logo.png" }, { "Type":"sap.ui.commons.Button", "id":"MyButton", "text":"Press Me" }] }
So you simply nest the JSON Objects like you want to nest the SAPUI5 controls and add the property values as attributes. The syntax is exactly the same as you can use a JSON constructor for any control. Note: You can only use strings in your JSONView.
MY_TEXT=Hello World
Example:
"Type": "sap.ui.core.JSONView", "controllerName":"my.own.views.test", "resourceBundleName":"myBundle", "resourceBundleAlias":"i18n", "content": [{ "Type":"sap.ui.commons.Panel", "id":"myPanel", "content":[{ "Type":"sap.ui.commons.Button", "id":"Button1", "text":"{i18n>MY_TEXT}", "press": "doIt" }] }]
}
The necessary ResourceModel for binding this texts is created during View instantiation. The Model will be set as secondary Model with the given alias to the View instance. If you want to bind other properties to another Model you have to create the Model on your own within the corresponding Controller, or HTML page, and attach it to the View with another alias. The binding itself behaves like every SAPUI5 databinding and like described above.
View Instantiation
Views can be instantiated with the factory method sap.ui.view. Necessary information for the instantiation can be passed via an object. This object can have the following properties:
type: Type can be JSON, JS, XML. All possible types are declared in the enumeration sap.ui.core.mvc.ViewType viewName: The View name, corresponding to the module concept viewContent: XMLViews/JSONViews only - XML/JSON string representation of the View definition. If viewName and viewContent are given, the View definition will be loaded with the viewName Controller: Any Controller instance. The given Controller instance overrides the
Controller defined in the View definition viewData: JSViews only - can hold user specific data. This data is available during the whole lifecycle of the View and the Controller
Example:
... var myController = sap.ui.controller("my.own.controller"); var myView = sap.ui.view({ type: sap.ui.core.mvc.ViewType.XML, viewName: "my.own.view", controller: myController
}); ...
All regular properties of a View (control) can be passed to the object as usual.
/* boilerplate code for typed Controller */ jQuery.sap.declare({modName:"sap.hcm.AddressController", type:"controller"}); // declaring a special type of module sap.hcm.AddressController = function () { // the constructor sap.ui.core.mvc.Controller.apply(this, arguments); }; jQuery.sap.require("sap.ui.core.mvc.Controller"); // this is currently required, as the Controller is not loaded by default sap.hcm.AddressController.prototype = jQuery.sap.newObject(sap.ui.core.mvc.Controller.prototype); // chain the prototypes /* end of boilerplate code for typed Controller */ // to avoid the above we could in the future offer it behind a simple call to: // sap.ui.defineController("sap.hcm.Address"); sap.hcm.AddressController.prototype.onInit = function() { // modify control tree - this is the regular lifecycle hook }; // implement an event handler in the Controller sap.hcm.AddressController.prototype.doSomething = function() { alert("Hello World"); };
A live example can be found here. Or you can view the example in snippix.
Nesting Views
All Views can be nested independent of the View type. Each View type behaves like any other SAPUI5 control. The viewName property defines which View to embed. For XMLViews it can look like this:
<core:View controllerName="sap.hcm.Address" xmlns="sap.ui.commons" xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml"> <Panel> <core:JSView id="myJSView" viewName="sap.hcm.Bankaccount" /> </Panel> <core:View>
<core:View viewName="sap.hcm.ButtonView" controllerName="sap.hcm.myController" xmlns="sap.ui.commons" xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml"> <Button id="aButton" text="Click me"/> <core:View>
This View defines a Button with static ID aButton. ContainerView:
<core:View viewName="sap.hcm.ContainerView" controllerName="sap.hcm.Address" xmlns="sap.ui.commons" xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml"> <core:View id="ButtonView1" viewName="sap.hcm.ButtonView"/> <core:View id="ButtonView2" viewName="sap.hcm.ButtonView"/> <core:View>
This View defines a View embedding the same View several times. View creation:
-ButtonView1 myContainerView--ButtonView2
Getting one of these child Views:
Under Development
Performance measurements for XML parsing Useful connecting methods between Controller and other entities may need to be added in the future Controls - like Dialogs - that are not part of the UI tree Preserve/rendering issue when using HTML container in XMLViews