2.2. New controllers, views and classes
2.2.1. App.controller.js/App.view.XML modification
2.2.4. Main.controller.js/Main.view.XML
2.2.5. NotFound.controller.js/NotFound.viiw.XML
2.3. Component, Manifest and Routing
sap.ui.define([
"./BaseController",
"sap/ui/model/json/JSONModel",
"sap/ui/core/routing/History"
], function(BaseController, JSONModel, History) {
"use strict";
return BaseController.extend("AppTemplate.controller.App", {
onInit: function() {
// declare controller variable
var oViewModel,
fnSetAppNotBusy,
iOriginalBusyDelay = this.getView().getBusyIndicatorDelay();
/*
Create the model for your view.
This model can set/reset all specific view paramaters.
In this case we want to set busy and delay values
*/
oViewModel = new JSONModel({
busy: true,
delay: 0
});
/*
set model to our view which actually will be set in BaseController.
This is simple example of resuing our code. You can always refer to
function in BaseController from any view in your app
*/
this.setModel(oViewModel, "appView");
// function remove busy indicator
fnSetAppNotBusy = function() {
oViewModel.setProperty("/busy", false);
oViewModel.setProperty("/delay", iOriginalBusyDelay);
};
/*
use promise to check if metadata from our service is loaded.
If so run function fnSetAppNotBusy which set busy to false.
It will run only once just on start of the application.
The user wont be able to do anything unless service is avilable
*/
this.getOwnerComponent().getModel().metadataLoaded().
then(fnSetAppNotBusy);
// apply content density mode to root view
this.getView().addStyleClass(this.getOwnerComponent().getContentDensityClass());
}
});
});
<mvc:View controllerName="AppTemplate.controller.App" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
busy="{appView>/busy}"
busyIndicatorDelay="{appView>/delay}">
<App id="app"/>
</mvc:View>
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/format/DateFormat",
"sap/ui/core/MessageType",
"sap/ui/core/routing/History"
], function(Controller, History) {
"use strict";
return Controller.extend("AppTemplate.controller.BaseController", {
/*
Using this function you can manipulate router on any view.
Just remember to call it first on view
*/
getRouter: function() {
return sap.ui.core.UIComponent.getRouterFor(this);
},
/*
By calling this function in your view you can set translated texton view.
Example: 'this.getResourceBundle().getText("Main.saveButton");'
*/
getResourceBundle: function() {
return this.getOwnerComponent().getModel("i18n").getResourceBundle();
},
/*
Use this when you set an action on Back button on any view.
If you have history it will show you the previous view
if not router wil redirect you to first view of your app
*/
onNavBack: function(oEvent) {
var oHistory, sPreviousHash;
oHistory = History.getInstance();
sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getRouter().navTo("appMain", {}, true /*no history*/ );
}
},
/*
Getter and setter for model.
*/
getModel: function(sName) {
return this.getView().getModel(sName);
},
setModel: function(oModel, sName) {
return this.getView().setModel(oModel, sName);
}
});
});
sap.ui.define([
"sap/ui/base/Object",
"sap/m/MessageBox"
], function(Object, MessageBox) {
"use strict";
return Object.extend("AppTemplate.controller.ErrorHandler", {
/**
* Handles application errors by automatically attaching to the model events and displaying errors when needed.
* @class
* @param {sap.ui.core.UIComponent} oComponent reference to the app's component
* @public
* @alias mycompany.myapp.controller.ErrorHandler
*/
constructor: function(oComponent) {
this._oResourceBundle = oComponent.getModel("i18n").getResourceBundle();
this._oComponent = oComponent;
this._oModel = oComponent.getModel();
this._bMessageOpen = false;
this._sErrorText = this._oResourceBundle.getText("errorText");
this._oModel.attachMetadataFailed(function(oEvent) {
var oParams = oEvent.getParameters();
this._showMetadataError(oParams.response);
}, this);
this._oModel.attachRequestFailed(function(oEvent) {
var oParams = oEvent.getParameters();
// An entity that was not found in the service is also throwing a 404 error in oData.
// We already cover this case with a notFound target so we skip it here.
// A request that cannot be sent to the server is a technical error that we have to handle though
if (oParams.response.statusCode !== "404" || (oParams.response.statusCode === 404 && oParams.response.responseText.indexOf(
"Cannot POST") === 0)) {
this._showServiceError(oParams.response);
}
}, this);
},
/**
* Shows a {@link sap.m.MessageBox} when the metadata call has failed.
* The user can try to refresh the metadata.
* @param {string} sDetails a technical error to be displayed on request
* @private
*/
_showMetadataError: function(sDetails) {
MessageBox.error(
this._sErrorText, {
id: "metadataErrorMessageBox",
details: sDetails,
styleClass: this._oComponent.getContentDensityClass(),
actions: [MessageBox.Action.RETRY, MessageBox.Action.CLOSE],
onClose: function(sAction) {
if (sAction === MessageBox.Action.RETRY) {
this._oModel.refreshMetadata();
}
}.bind(this)
}
);
},
/**
* Shows a {@link sap.m.MessageBox} when a service call has failed.
* Only the first error message will be display.
* @param {string} sDetails a technical error to be displayed on request
* @private
*/
_showServiceError: function(sDetails) {
if (this._bMessageOpen) {
return;
}
this._bMessageOpen = true;
MessageBox.error(
this._sErrorText, {
id: "serviceErrorMessageBox",
details: sDetails,
styleClass: this._oComponent.getContentDensityClass(),
actions: [MessageBox.Action.CLOSE],
onClose: function() {
this._bMessageOpen = false;
}.bind(this)
}
);
}
});
});
sap.ui.define([
"./BaseController",
"sap/ui/model/json/JSONModel"
], function(BaseController, JSONModel) {
"use strict";
return BaseController.extend("AppTemplate.controller.Main", {
/*
This function will run only once at the first call of the view
*/
onInit: function() {
//put your logic here
// As always, create view model here
var oViewModel = new JSONModel({
calSelectedDate: new Date(),
isDateModified: false
});
// and set it for this view
this.setModel(this.oViewModel, "MainView");
// call instance of the router and check is it correct
var oRouter = this.getRouter();
oRouter.getRoute("appMain").attachMatched(this._onRouteMatched, this);
},
// checking if declared route is matched
_onRouteMatched: function(oEvent) {
/*
Put you logic here.
Note that this will be call by every enter into this view.
Once again if you want something to run only once add that code to onInit function.
*/
}
});
});
<mvc:View controllerName="AppTemplate.controller.Main" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc"
displayBlock="true" xmlns="sap.m">
<App>
<pages>
<Page title="{i18n>title}">
<content>
</content>
</Page>
</pages>
</App>
</mvc:View>
sap.ui.define([
"./BaseController"
], function(BaseController) {
"use strict";
return BaseController.extend("AppTemplate.controller.NotFound", {
});
});
<mvc:View controllerName="AppTemplate.controller.NotFound" xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">
<MessagePage title="{i18n>NotFound}" text="{i18n>NotFound.text}" description="{i18n>NotFound.description}" showNavButton="true"
navButtonPress="onNavBack"/>
</mvc:View>
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"AppTemplate/model/models",
"AppTemplate/controller/ErrorHandler"
], function(UIComponent, Device, models, ErrorHandler) {
"use strict";
return UIComponent.extend("AppTemplate.Component", {
metadata: {
manifest: "json"
},
/**
* The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
* @public
* @override
*/
init: function() {
// call the base component's init function
UIComponent.prototype.init.apply(this, arguments);
// initialize the error handler with the component
this._oErrorHandler = new ErrorHandler(this);
// set the device model
this.setModel(models.createDeviceModel(), "device");
// create the views based on the url/hash
this.getRouter().initialize();
},
destroy: function() {
this._oErrorHandler.destroy();
// call the base component's destroy function
UIComponent.prototype.destroy.apply(this, arguments);
},
getContentDensityClass: function() {
if (this._sContentDensityClass === undefined) {
// check whether FLP has already set the content density class; do nothing in this case
if (jQuery(document.body).hasClass("sapUiSizeCozy") || jQuery(document.body).hasClass("sapUiSizeCompact")) {
this._sContentDensityClass = "";
} else if (!Device.support.touch) {
// apply "compact" mode if touch is not supported
this._sContentDensityClass = "sapUiSizeCompact";
} else {
// "cozy" in case of touch support; default for most sap.m controls, but needed for desktop-first controls like sap.ui.table.Table
this._sContentDensityClass = "sapUiSizeCozy";
}
}
return this._sContentDensityClass;
}
});
});
{
"_version": "1.5.0",
"sap.app": {
"id": "AppTemplate",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "ui5template.basicSAPUI5ApplicationProject",
"version": "1.40.12"
},
"dataSources": {
"main": {
"uri": "/sap/opu/odata/SAP/YOUR_ODATA/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone@2": "",
"tablet": "",
"tablet@2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_hcb",
"sap_belize"
]
},
"sap.ui5": {
"rootView": {
"viewName": "AppTemplate.view.App",
"type": "XML"
},
"dependencies": {
"minUI5Version": "1.30.0",
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.ui.layout": {},
"sap.ushell": {},
"sap.collaboration": {},
"sap.ui.comp": {},
"sap.uxap": {}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "AppTemplate.i18n.i18n"
}
},
"": {
"dataSource": "main",
"type": "sap.ui.model.odata.v2.ODataModel",
"settings": {
"loadMetadataAsync": true,
"json": true,
"bJSON": true,
"defaultBindingMode": "TwoWay",
"useBatch": true,
"refreshAfterChange": false,
"disableHeadRequestForToken": true
}
}
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "AppTemplate.view",
"controlId": "app",
"controlAggregation": "pages",
"transition": "slide",
"bypassed": {
"target": "notFound"
}
},
"routes": [{
"pattern": "",
"name": "appMain",
"target": "main"
}],
"targets": {
"main": {
"viewName": "Main",
"viewLevel": 1
},
"notFound": {
"viewName": "NotFound",
"transition": "show"
}
}
},
"resources": {
"css": [{
"uri": "css/style.css"
}]
}
}
}
"rootView": {
"viewName": "AppTemplate.view.App",
"type": "XML"
}
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "AppTemplate.view",
"controlId": "app",
"controlAggregation": "pages",
"transition": "slide",
"bypassed": {
"target": "notFound"
}
},
"routes": [{
"pattern": "",
"name": "appMain",
"target": "main"
}],
"targets": {
"main": {
"viewName": "Main",
"viewLevel": 1
},
"notFound": {
"viewName": "NotFound",
"transition": "show"
}
}
},
{
"path": "/sap/opu/odata",
"target": {
"type": "destination",
"name": "NAME_OF_YOUR_DEV_SERVER",
"entryPath": "/sap/opu/odata"
},
"description": "NAME_OF_YOUR_DEV_SERVER"
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
6 | |
5 | |
5 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 |