In step 16 we created a dialog as fragment, because we wanted it to be reusable across views or across our whole app. But we placed the logic for retrieving the dialog instance and for opening and closing it respectively in the controller of the HelloPanel view. Sticking to this approach would require copying and pasting the code to the controller of each view that needs our dialog. This would of course cause an undesired code redundancy we definitely want to avoid. In this step, we will implement the solution to this problem: We now expand our reuse concept and invoke the dialog at component level.
You can view and download all files in the Explored app in the Demo Kit under Walkthrough - Step 19.
sap.ui.define([ "sap/ui/core/UIComponent", "sap/ui/model/json/JSONModel", "sap/ui/demo/wt/controller/HelloDialog" ], function (UIComponent, JSONModel, HelloDialog) { "use strict"; return UIComponent.extend("sap.ui.demo.wt.Component", { metadata : { manifest : "json" }, init : function () { // call the init function of the parent UIComponent.prototype.init.apply(this, arguments); // set data model var oData = { recipient : { name : "World" } }; var oModel = new JSONModel(oData); this.setModel(oModel); // set dialog this.helloDialog = new HelloDialog(); } }); });
The dialog instantiation is refactored to a new helper object that we can directly access through the component. In its initialization method we store a public reference to it that can be accessed from every controller.
sap.ui.define([
"sap/ui/base/Object"
], function (Object) {
"use strict";
return Object.extend("sap.ui.demo.wt.controller.HelloDialog", {
_getDialog : function () {
// create dialog lazily
if (!this._oDialog) {
// create dialog via fragment factory
this._oDialog = sap.ui.xmlfragment("sap.ui.demo.wt.view.HelloDialog", this);
}
return this._oDialog;
},
open : function (oView) {
var oDialog = this._getDialog();
// connect dialog to view (models, lifecycle)
oView.addDependent(oDialog);
// open dialog
oDialog.open();
},
onCloseDialog : function () {
this._getDialog().close();
}
});
});
The implementation of the HelloDialog reuse object extends a base object to inherit the core functionality of SAPUI5.
Our _getDialog method is refactored from the HelloPanel controller and instantiates our dialog fragment as in the previous steps. Note that now the reuse object is passed on as a controller to the fragment.
The open method now contains our dialog instantiation. The first time the open method is called, the dialog is instantiated. The oView argument of this method is used to connect the current view to the dialog. We will call the open method of this object later in the controller.
The onCloseDialog event handler is simply moved from the HelloPanel controller to the reuse object.
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast"
], function (Controller, MessageToast) {
"use strict";
return Controller.extend("sap.ui.demo.wt.controller.HelloPanel", {
onShowHello : function () {
// read msg from i18n model
var oBundle = this.getView().getModel("i18n").getResourceBundle();
var sRecipient = this.getView().getModel().getProperty("/recipient/name");
var sMsg = oBundle.getText("helloMsg", [sRecipient]);
// show message
MessageToast.show(sMsg);
},
onOpenDialog : function () {
this.getOwnerComponent().helloDialog.open(this.getView());
}
});
});
The onOpenDialog method now accesses its component by calling the helper method getOwnerComponent. When calling the open method of the reuse object we pass in the current view to connect it to the dialog.
<mvc:View
controllerName="sap.ui.demo.wt.controller.App"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true">
<App class="myAppDemoWT">
<pages>
<Page title="{i18n>homePageTitle}">
<headerContent>
<Button
icon="sap-icon://hello-world"
press="onOpenDialog"/>
</headerContent>
<content>
<mvc:XMLView viewName="sap.ui.demo.wt.view.HelloPanel"/>
</content>
</Page>
</pages>
</App>
</mvc:View>
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller) {
"use strict";
return Controller.extend("sap.ui.demo.wt.controller.App", {
onOpenDialog : function () {
this.getOwnerComponent().helloDialog.open(this.getView());
}
});
});
We add the method onOpenDialog also to the app controller so that the dialog will open with a reference to the current view.
Put all assets that are used across multiple controllers in separate modules.