How to start XML preprocessor without return a view component - sapui5

I'm trying to create a launchpad for a set of applications that we use here. One of my problems is that I need to add different tiles in a tile container (slide,custom,standard, etc) and what I think that may be a solution is use XML templating to do that. What I want to achieve is something like that:
<TileContainer id="tileList"
allowAdd="true"
tileDelete="onDelete"
tiles="{path:'Atalhos>/' ,sorter:{path:'Atalhos>TileText',group:false}}">
<template:if test="{path:'Atalhos>TileCode', operator:'EQ',value1:'teste1'}">
<template:then>
<core:Fragment fragmentName="pelissari.soficom.launchpad.view.StandardTile" type="XML"/>
</template:then>
<template:else>
<core:Fragment fragmentName="pelissari.soficom.launchpad.view.StandardTile" type="XML"/>
</template:else>
</template:if>
</TileContainer>
but the problem is that I'm having this error when I try to do that.
UIComponent-dbg.js:52 Uncaught Error: failed to load
'http://schemas/sap/com/sapui5/extension/sap/ui/core/template/1/if.js'
from
resources/http://schemas/sap/com/sapui5/extension/sap/ui/core/template/1/if.js:
404 - Not found
I know that I need to start the preprocessor to use preprocessing instructions but all the examples that I found makes me more confuse that I was before.
My project is based on the sapui5 tutorial "WalkThrough where I have a component that starts an app view configured in the manifest and this view is navigate to the launchpad view by routing configuration again in the mainfest. all the examples create a view in the component CreateComponent function or in some controller function that loads other view. I just need to start the preprocessor for the list of tiles that I load from the entity set "/TileSet".

I found another way to do what I want. Now I'm using factory function to create the tiles as I need.
tileFactory: function(sId, oContext) {
var atalho = oContext.getProperty(oContext.sPath)
var oUIControl = null;
if (atalho.TileCode == 'teste2') {
oUIControl = new sap.m.StandardTile(sId, {
title: atalho.TileText
});
oUIControl.addStyleClass('tileSize3');
} else {
oUIControl = new sap.m.StandardTile(sId, {
title: atalho.TileText
});
oUIControl.addStyleClass('tileSize1');
}
oUIControl.attachPress(this.onPress, this);
oUIControl.addStyleClass('tile');
return oUIControl;
}
<Page id="tileGroup" showHeader="true"
content="{path:'Atalhos>/' ,sorter:{path:'Atalhos>TileOrder',group:false},factory:'.tileFactory'}">

Related

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

Setting multiple properties of a component with one function

I have a component in a list in a sapui5 XML view and I want to set multiple properties of that component with one function. E.g. I want to set text, status, tooltip and icon of an ObjectStatus together, because the values of those are all different facets of the same data. The issue is that i have to calculate the values to set to those properties from the model with the same relatively time-heavy function. If I write a separate formatter for each of those properties, it has to run the same function for each property. Instead of this I would like to write one function that runs this time-heavy function once and sets a value to all those properties at the same time.
To accomplish this, I have tried creating a sapui5 fragment that could be placed in the list and filled with different information by the createContent function for each instance of that fragment. However I cannot figure out how to do this.
In the view definitions I'm trying to instantiate the fragment like this:
<core:Fragment fragmentName="QuantificationParameter" type="JS" path="{project>}"/>
And then I'm trying to set different content to each instance of the fragment:
sap.ui.jsfragment("namespace.fragments.QuantificationParameter", {
createContent: function(oParentController) {
//Get the object bound to this list item
var derived; //Calculate some intermediate information from this object
return new sap.m.ObjectStatus({
icon: derived.icon,
text: derived.text,
state: derived.state,
tooltip: derived.tooltip
});
}
});
While debugging it seems that the createContent function of the fragment is run only once and I cannot figure out any way to access the data that I'm trying to bind to the fragment. Is there any way I can render different content to each instance of the fragment?
What you are searching for is called databinding.
But first of all: we do not use JS Fragments, due to the same reason we do not use JS views. Here s a little Blog written on that topic.
https://blogs.sap.com/2018/05/01/why-do-we-use-xml-views-rather-js-views-in-sapui5/
Now the databinding part:
I asume, that Fragment will have the same controlls for each instance and you just want the values to change. To do just that you need to create a JSONModel either in your BaseController or component.js. In this Model you store i.e. your Labels text.
Inside your Fragmet you bind that property to the label. Since JSONModels bindingmode is two way by default the Label will change dynamically if you update the model. You can update the model i.e. everytime the user clicks on one of your list items.
Framgmet example:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core">
<f:SimpleForm
editable="true">
<f:content>
<Input
value="{baseModel>/inputA}"
type="Text"
placeholder="{i18n>placeHolder}"/>
<TextArea
value="{baseModel>/textA}"/>
<TextArea
editable="false"
value="{baseModel>/textB}"/>
</f:content>
</f:SimpleForm>
</core:FragmentDefinition>
creation of the model i.e in component.js:
var oBaseModel = new JSONModel({
inputA: "",
textA: "",
textB: ""
});
this.setModel(oBaseModel, "baseModel");
example for your press lit item funtion:
(should be in the controller of the view your list is located in)
onListPress: function (oEvent) {
var oLine = oEvent.getSource().getBindingContext("yourRemoteService").getObject();
this._oBaseModel.setProperty("/inputA", oLine.ListPropertyA);
this._oBaseModel.setProperty("/textA", oLine.ListPropertyb);
this._oBaseModel.setProperty("/textB", oLine.ListPropertyC);
}
You should really give that tutorial a go:
https://sapui5.hana.ondemand.com/#/topic/e5310932a71f42daa41f3a6143efca9c

How to set ID of a XML-View in a component environment?

I want to access a view's controller from a custom module with some utility functions. Basically you can do this that way:
var oController = sap.ui.getCore().byId("__xmlview1").getController();
The problem is that the above coding will not work in a real environment because __xmlview1is dynamically created by the framework. So I tried to find a possibility to set the ID of the view during instantiation. The problem is - I could not find one:
Trying to give the view an ID in the view.xml file does not work:
<mvc:View
controllerName="dividendgrowthtools.view.dividendcompare"
id="testID"
xmlns="sap.m"
...
Trying to set the ID in the router configuration of the component does not work either:
...
name: "Dividend Compare",
viewId: "test",
pattern: "Dividend-Compare",
target: "dividendcompare"
...
The problem is that I do not have direct control over the instantiation of the XML view - the component respectively the router does it.
So, is there a solution for that problem? Or at least a save way to get the view ID by providing the name of the view?
You should have a look at the SAPUI5 EventBus.
I am pretty sure, you want to let the controller to do something with the dividentcompare view. With the SAPUI5 Eventbus, you can publish actions from one controller to another witout braking MVC patterns.
In your dividendcompare.controller.js:
onInit : function() {
var oEventBus = sap.ui.getCore().getEventBus();
oEventBus.subscribe("MyChannel", "doStuff", this.handleDoStuff, this);
[...]
},
handleDoStuff : function (oEvent) {
var oView = this.getView();
[...]
}
Now, in your anothercontroller.controller.js:
onTriggerDividendStuff : function (oEvent){
var oEventBus = sap.ui.getCore().getEventBus();
oEventBus.publish("MyChannel", "doStuff", { [optional Params] });
}
You are now able to get the view from the dividentcontroller in every case from every other controller of your app. You dont access the view directly, this would brake MVC patterns, but can pass options to its controller and do the handling there.

Link to route without additional JS code

I'm a beginner to OpenUI5 and have written a menu like below:
view:
<NavigationList id="navigationList" width="12rem">
<NavigationListItem text="People" icon="sap-icon://card" select="goToRoute"></NavigationListItem>
</NavigationList>
controller:
goToRoute: function() {
this.getRouter().navTo("peoplelist");
}
That works, but it's bad, as I have a couple of menu items and JS events for each of them.
I wish I had something like this below, without any JS behind, but couldn't find anything in documentation and examples.
view:
<NavigationList id="navigationList" width="12rem">
<NavigationListItem text="People" icon="sap-icon://card" linkToRoute="peoplelist"></NavigationListItem>
</NavigationList>
Anyone knows?
You can build a generic event handler which derives the target route from the corresponding item. To achieve this you can make use of custom data which you can add to controls in a declarative way. For this add the following line to your opening View tag:
xmlns:custom="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"
Adopt your navigation list:
<NavigationList id="navigationList" width="12rem">
<NavigationListItem text="People" icon="sap-icon://card" select="onItemSelect" custom:route="peopleList"/>
</NavigationList>
And your controller:
onItemSelect : function(event) {
var item = event.getSource();
var route = item.data("route");
this.getRouter().navTo(route);
}
Here you find further details.

In AEM6, How do I hide a specific component field based on pages for certain country only?

In AEM6, How do I hide a specific component field based on pages for certain country only ?
You can write custom dialog/widget plugin to do that. This is how you attach plugin to your widget:
<title jcr:primaryType="cq:Widget"
fieldLabel="Field to hide"
plugins="hideFieldPlugin"
name="./fieldToHide"
xtype="textfield" />
Next, we need to write plugin and register it:
(function ($) {
var plugin = CQ.Ext.extend(CQ.Ext.emptyFn, {
init: function (fieldToHide) {
var url = CQ.HTTP.getPath();
if (this.shouldBeHidden(url)) {
fieldToHide.hide().disable();
}
},
shouldBeHidden: function (url) {
// some logic
return true;
}
});
CQ.Ext.ComponentMgr.registerPlugin("hideFieldPlugin", plugin);
}($CQ));
JavaScript file needs to be included in Classic UI edit mode. Best way to do that is to use your own custom clientlib or use already existing category, cq.wcm.edit.
If you have more complex logic which goes across multiple widgets, you can attach plugin on dialog level and navigate to the widget objects using dialog.find method.