Using SearchField Inside Popover Keeps on Emitting 'select' Event and Rerenders Popover - sapui5

I am using a custom control for a popover like this:
sap.ui.define([
"sap/m/Popover"
], function(Popover) {
"use strict";
return Popover.extend("name of controle", {
init: function() {
Popover.prototype.init.apply(this, arguments);
this.oPopup.setAutoClose(false);
},
renderer : "sap.m.PopoverRenderer"
});
});
And I am using this popover custom control like this:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:path="path to custom popover"
>
<path:CustomPopover
placement="Left"
contentHeight="80%"
contentWidth="25%"
>
<path:content>
<!-- xmlview that has search field in it -->
</path:conent>
</path:CustomPopover>
</core:FragmentDefinition>
Now, if I use this fragment to create Popover, then the select event keeps on emitting for that search field.
2017-02-15 09:53:47.456659 Event fired: 'select' on Element sap.m.SearchField#__field0 - sap.ui.core.UIArea
This popover works fine in chrome even after continuous emission of an event but in Internet Explorer, it keeps on rerendering, so not able to use it. How to fix this?

Related

<Component> is not defined in SAPUI5

I tried to set up UI5 development on my local machine follow this turoial. The general setup seems to be fine, but when I add a button and want to let it show a MessageToast or a MessageBox (since I've read that MessageToast is deprecated) it does not work. The Button is showed, but when I click on it I get the following issues:
In Edge Developer Tools: "MessageToast is not defined" (same with MessageBox)
In Console: Error: connect ECONNREFUSED 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16)
Here is my coding:
View:
<mvc:View controllerName="testproject.controller.Test123"
xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
xmlns="sap.m">
<Page id="page" title="{i18n>title}">
<content>
<Button id="test" text="Press Button" press="onClick"/>
</content>
</Page>
</mvc:View>
Controller:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast",
"sap/m/MessageBox"
],
/**
* #param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller) {
"use strict";
return Controller.extend("testproject.controller.Test123", {
onInit: function () {
},
onClick: function() {
//MessageToast.show("Test");
MessageBox.information("Test2");
}
});
});
I tried this via VS-Code and since I could not be sure if my setup is wrong I used the trial instance of the BAS. So if you want to reproduce it, just generate a freestyle UI5 project via BAS (or VS-Code) and then basically just add the button and the code of the controller. I've done nothing more.
I am running on UI5 version 1.48.0, have chosen no data source (would have added it manually later, since I just wanted to test first) and thats it. maybe you can tell me what I am missing (I programmed UI5 in the past and this was basically also more or less my hello world, but I can't get my head around what is wrong this time)
You import 3 dependencies here
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast",
"sap/m/MessageBox"
],
but only 1 of them (the first) will be accessible because you didn't add them to the method signature here
function (Controller) {
So just add the other dependencies to your signature
function (Controller, MessageToast, MessageBox) {

FlexibleColumnLayout on second view not working SAP UI5

I am building a view with hardcoded data. which comes from home screen to the next view which is supposed to be a split view screen.
I am using FlexibleColumnLayout and inside of it begin and end layout to call views from my view folder. I have been following this tutorial. and even then my split view is not expanding on click.
My aggregation looks like this (I am not sure if it is correct):
App -> (View1, FCLView)
FCLView -> (MasterVIew, DetailView)
FCLView:
<mvc:View displayBlock="true" height="100%" xmlns="sap.f" xmlns:mvc="sap.ui.core.mvc">
<FlexibleColumnLayout id="flexibleColumnLayout" backgroundDesign="Solid">
<beginColumnPages>
<mvc:XMLView id="beginView" viewName="Ui5.Ui.view.MasterView"/>
</beginColumnPages>
<midColumnPages>
<mvc:XMLView id="detailView" viewName="Ui5.Ui.view.DetailView"/>
</midColumnPages>
</FlexibleColumnLayout>
</mvc:View>
component.js
...
getHelper: function () {
var oFCL = this.getRootControl().byId('flexibleColumnLayout'),
oSettings = {
defaultTwoColumnLayoutType: sap.f.LayoutType.TwoColumnsMidExpanded,
initialColumnsCount: 2
};
return FlexibleColumnLayoutSemanticHelper.getInstanceFor(oFCL, oSettings);
}
MasterViewController
...
onListItemPress: function (oEvent) {
MessageToast.show("here");
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
var oFCL = this.oView.getParent().getParent();
oFCL.setLayout(fioriLibrary.LayoutType.TwoColumnsMidExpanded);
}
I am following this tutorial
The scenario is, I have my first fullscreen view (View1) in which there's a button and it will navigate to second view which is a split view. (table and on clicking a row, the detail view will expand).
I am new to SAP, any kind of help would be appreciated.
It is difficult to debug your code excerpts, because there are several other things that can go wrong. (e.g. did you configure the use the sap.f.router instead of the sap.m.router in the manifest?)
The easiest way to start with a FlexibleColumnLayout is to begin with the UI5 MasterDetail-Template
This can be downloaded from Github or easily created in the WebIDE with a few clicks (new Project from template -> select Master Detail Application)
You can read more about the Template in the Demokit

Getting the oData in the event handler of Fiori Launchpad header event

I would like to check for data changes when the user clicks on the back button in the Fiori Launchpad. I have the following code
onAfterRendering: function() {
sap.ui.getCore().byId("backBtn").attachPress(this, function(oEvent) {
oEvent.preventDefault();
});
}
Within the function I would like to access the oData and other variables of the main controller. However when I press the back button the "this" object is the header control's view.
How can get the view of the page content and also access the oData and other parameters of the controller associated to the content view.
In order to access the current context you have to call the event handler function within that specific context, so therefore a binding is needed on that function.
onAfterRendering: function() {
sap.ui.getCore().byId("backBtn").attachPress(this, function(oEvent) {
oEvent.preventDefault();
}.bind(this));
}
If usage of sap.m.Page is an option than navButtonPress builtin event can be used:
View.xml:
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">
<Page navButtonPress="onNavBack">
...
Controller.js:
onNavBack: function(oControlEvent) {
var oController = this;
var oView = this.getView();
}
the event listener will be triggered every time the button is pressed in the Fiori Launchpad header.

SAP Fiori: Back button in fragments

I am working on a SAP Fiori app and I am stuck in this problem for about 2 weeks with no result. I have a "create" fragment which is attached to "Detail" view.
When I open the "create" fragment and want to go back to the main detail view, the back button doesn't work therefore I have to refresh the app.
I guess the back button doesn't work the same way between views & between fragments.
Here's my back button function :
cancel: function() {
var oHistory = sap.ui.core.routing.History.getInstance(),
sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
// The history contains a previous entry
history.go(-1);
}
},
Here when I display sPreviousHash, it's undefined. Why?
Where is the back button that you are referring to?
I would expect that the fragment is a dialog and therefore that there is no back button. A close button is needed which will result in the fragment being closed. Depending on the requirements, the back navigation could then be done from the controller where the fragment was created.
Fragments are a technique to reuse UI parts, but are not part of the MVC concept. You cannot navigate directly to/from a fragement and this has to be done using views. Therefore the history is not available in a fragment. The BROWSER back button will take you to the previous screen in the BROWSER history.
Controller of the view in which the fragment as a dialog is opened.
_initializeReviewDialog: function() { this._oReviewDialog = sap.ui.xmlfragment(this.getView().getId(), "ReviewDialog", this);
this.attachControl(this._oReviewDialog);
},
Event in View that triggers the dialog opening
onEditReviewPressed: function(oEvent) {
if (!this._oReviewDialog) {
this._initializeReviewDialog(); }
}
this._oReviewDialog.open();
},
onReviewDialogOKPressed: function(oEvent) {
this._oReviewDialog.close();
},
Add fragment as a Dependent, so that models and events from owning view/controller are know
attachControl: function(oControl) {
var sCompactCozyClass = this.getOwnerComponent().getContentDensityClass();
jQuery.sap.syncStyleClass(sCompactCozyClass, this.getView(), oControl);
this.getView().addDependent(oControl);
},
FragmentDefinition
<core:FragmentDefinition id="ReviewDialogFragment" xmlns="sap.m" xmlns:l="sap.ui.layout"
xmlns:core="sap.ui.core">
<Dialog id="reviewDialog" >
<content>
... </content>
<beginButton>
<Button id="btnOK" text="{i18n>xbut.ok}" press="onReviewDialogOKPressed"/>
</beginButton> </Dialog>
</core:FragmentDefinition>

Shared event handler for XML views with different controllers

Given two XML Views:
<mvc:View
controllerName="my.namespace.controller.First"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<Button press=".onBtnPress" />
</mvc:View>
<mvc:View
controllerName="my.namespace.controller.Second"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<Button press=".onBtnPress" />
</mvc:View>
As expected, the press event is handled by First.controller.js or Second.controller.js.
Instead of duplicating the event handler code or implementing handlers in each Controller to chain/hand off the work, I want to declare a shared event handler.
According to docs this should be possible, using a naming convention for the handler:
Names starting with a dot ('.') are always assumed to represent a method in the controller.
Names containing a dot at a later position are assumed to represent global functions and are resolved by calling jQuery.sap.getObject with the full name.
So I change the handler and declare a shared object, like so:
First.view.xml:
<Button press="my.namespace.Shared.onBtnPress" />
Shared.js:
jQuery.sap.declare("my.namespace.Shared");
my.namespace.Shared = (function() {
var onBtnPress = function() {
console.log("button pressed");
};
return { onBtnPress : onBtnPress };
}());
Warning logged (debug sources) during view initialisation:
sap.ui.core.mvc.XMLView#__xmlview1: event handler function "my.namespace.Shared.onBtnPress" is not a function or does not exist in the controller. -
Calling jQuery.sap.getObject("my.namespace.Shared") yields undefined
Same issue when using sap.ui.define to make the object known.
Since UI5 1.69, it has become easier to share JS modules in XML view and fragment.doc
Here is an example: https://embed.plnkr.co/5G80I5HWObCuM5cG
<mvc:View controllerName="..."
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:core="sap.ui.core"
core:require="{ onButtonPress: 'my/shared/onButtonPress' }">
<Button text="Press" press="onButtonPress" />
</mvc:View>
As we can see, each button displays a different message depending on the view, even though the handler itself isn't included in the controller definition.
The this context is still the controller instance as documented in the topic Handling Events in XML Views:
As long as no event handler parameters are specified and regardless of where the function was looked up, it will be executed with the controller as the context object (this).
Your shard object looks weird
Try something like this:
sap.ui.define([], function() {
return sap.ui.base.Object.extend("my.namespace.Shared", function() {
onBtnPress : function() {
console.log("button pressed");
}
};
});
Also remember to put the object in the right directory.
I was able to copy-paste your sap.ui.define and verified it was created correctly jQuery.sap.getObject.
Make sure that your sap.ui.define has been called prior to your view being rendered.
You can set a breakpoint in the XMLTemplateProcessor where the event callbacks are handled for XML views for further debugging/timing issues.
If you look in the _resolveEventHandler function it should take you here which will perform the jQuery.sap.getObject.