Component reuse in manifest.json file - sapui5

We are currently building a set of apps, where there is a lot of reuse.
Currently we got it working by using
jQuery.sap.registerModulePath and jQuery.sap.require.
But according to
Using and Nesting Components you should be able to declare your reuse components in the manifest.json file.
I had a look in the SAPUI5 Developer Guide, but couldn't really make it work. As far as i can see I need to add the following:
"sap.App" :{
"embeddedBy" : "../.."
},
"sap.ui5": {
"componentUsages" :{
"<string for my reuse component>" : {
"name" : "<name of the component>"
}
"dependencies" :{
"components" : {
"<namespace of my component>"
}}
Anyone got a working example?

Here is a working example with nested components: https://embed.plnkr.co/e7KS48/
The descriptor attribute componentUsages is available since 1.47.0. Once defined, UI5 takes care of resolving the Component and its module path before rendering the owning ComponentContainer.
ComponentContainer is needed because a Component cannot be placed into the UI without a container. In my example above, the Container is defined declaratively in Home.view.xml with the respective usage property.
<core:ComponentContainer id="containerForChildComponent"
autoPrefixId="true"
settings="{id: 'childComponent'}"
usage="reuseAnotherComponent"
manifest="true"
height="100%"
async="true"
/>
"sap.ui5": {
"componentUsages": {
"reuseAnotherComponent": {
"name": "anotherComponent",
"lazy": false
}
},
"resourceRoots": {
"anotherComponent": "./component_B"
},
// ...
}
As you can see, the resourceRoots can be also defined in the descriptor which could point to other component / app locations.
Example for UI5 apps w/ version below 1.47: https://embed.plnkr.co/ytXZJ9

Related

Creating a custom refinementList component based on two facets - Algolia

Let’s suppose we have these two facets:
“manufacturer.url”: [“/url1”, “/url2”, “/url3”]
AND
“manufacturer.name”: [“manufacturer1”, “manufacturer2”, “manufacturer3”];
I’d like to create a custom refinmentList component which show all available facets for my hits based on manufacturers.
I used connectRefinementList(MyCustomComponent); and I set manufactuer.url to attribute property.
<CustomManufacturerFilterRefinementList
attribute="manufacturer.url"
currentCategory={currentCategory}
limit={10}
locale={locale}
showMore={showMore}
searchable={searchable}
showMoreLimit={showMoreLimit}
translations={translations}
/>
Now users can see available manufacturers and can filter them or click on them to go to the manufacturer page, but since I fetch the manufacturer.url, I could only able to show the URL in the list, but I’d like to show manufacture’s name in the list and having URL to generate links.
Problem: how can I create a custom refinementList component which fetches data from two facets at the same time and combine them to generate a list of links?
PS: I tried to use searchForFacetValues function inside my custom component to retrvie manufacturer’s name with below query but I couldn’t map each url with name because there is no logical relation between them:
{
"requests": [
{
"indexName": "stg_lots",
"params": {
"facetName": [
"manufacturer.name"
],
"filters": "manufacturer.url:\"froemag\" OR manufacturer.url:\"volvo\" OR manufacturer.url:\"fendt\" ",
"maxFacetHits": 100
}
}
]
}
Thanks

Best practice to put all API Endpoints list in a file and use in a sapui5 application

I have bunch of API Endpoints as below:
BaseUrl
baseURL=****
create customer
createCustomer=api/customer/create
get customer
getCustomer=api/customer
...and so on
To use them in controller.js, I am storing them in i18n.properties file(am I doing this correct way?)
and referring as:
var url1=this.getView().getModel("i18n").getResourceBundle().getText("baseURL");
url2 = url2+this.getView().getModel("i18n").getResourceBundle().getText("getCustomer");
I guess there would be some other file where we would store all API's list as above scenario,
How this is commonly done in a sapui5 application, where these API Endpoints are stored and are used in controllers or in the application?
A sample example would be great to refer which might store API Endpoints ,along with how the API's are then called in controller.....
Any help is appreciated TIA!!
I usually like to maintain them in the "manifest.json" file (called also Application Descriptor file for UI5 apps).
There I create an entry inside dataSources property of the sap.app namespace:
"sap.app": {
"dataSources": {
"apiData": {
"uri": "api/folder/path",
"uri": "api/folder/path2",
"uri": "api/folder/path3"
}
}
},
In application code, I can retrieve those values by getting the metadata of the component:
apiSettings = sap.ui.getCore().getComponent("myAppComponent").getManifestEntry('sap.app').dataSources.apiData
A more elegant approach would be to define them in manifest as a dataSource but also in the sap.ui5 namespace, under models property:
"sap.app": {
"dataSources": {
"api": {
"uri": "api.json",
"type": "REST",
"settings": { }
}
}
},
...
"sap.ui5": {
...
"models": {
"api": {
"type": "sap.ui.model.json.JSONModel",
"uri": "api.json"
}
}
...
}
This way, UI5 will create a JSON model from a file called api.json on application load which you can read by using:
apiSettings = sap.ui.getCore().getComponent("lab").getModel('api').getData()
Check this link for more info about Application Descriptor:
https://sapui5.hana.ondemand.com/#/topic/be0cf40f61184b358b5faedaec98b2da

Dojo Build Tool

error(311) Missing dependency. module: app/ui/module/Widget1; dependency: appui/module/Widget2
The Dojo build tool does not take into consideration the configuration provided in the "paths" property of the Profile object
I have coded "paths" property as follows
paths : {
appui : "app/ui"
}
I don't believe "paths" is a valid property of the profile object.
The profile object often looks something like:
var profile = {
basePath:"/home/user/dev/",
releaseDir:"./release",
packages:[{
name:"dojo",
location:"./lib/dojo"
},{
name:"dijit",
location:"./lib/dijit"
},{
name:"myapp",
location:"./myapp"
}]
}
More info here: https://dojotoolkit.org/reference-guide/1.10/build/buildSystem.html#specifying-resources

SAPUI5 list is not auto-growing

I have a UI5 List which has the following attributes
growing="true"
growingTreshold="50"
growingScrollToLoad="true"
This list is inside a fragment which I include into my view. It used to work pretty well with my old project but unfortunatly since I refactored everything and included SAPUI5 Routing it doesn´t work anymore.
Now if I scroll down it shows me a [More] list item which shows the next 50 entries. Funny about that is, that I get an console error when I click on more stating
Uncaught Error: The segment {id} is required.
I guess this means the inhability of the list to auto-grow is somehow related to my new routing. The components I use look like this
{
pattern : "",
name : navigation.Constants.MyEvents,
view : navigation.Constants.MyEvents,
viewId : navigation.Constants.MyEvents,
targetAggregation : "pages",
targetControl : "idAppControl",
subroutes : [
{
pattern : "{id}",
name : navigation.Constants.EventDetailFragment,
view : navigation.Constants.EventDetailFragment
}
]
}
Does anyone now how to solve this problem? So far I couldn´t find anything related to my problem.
When navigating to the new page in your routing pass in the {id} parameter. i.e
this.getRouter().navTo("yourNewPage", {
from: currentView,
id: passedinHere
}, false);
Not having that is whats tripping up your code.

RESTful master/detail

Having 3 dropdown pickers in a web application. The web application uses a Restful service to populate pickers data.
The two first pickers get their values from something like /years and /colors. The third one should get its values depending on the settings of the two.
So it could be something like /models?year=1&color=red.
The question is, how to make this HATEOAS-compliant (so that the dev does not have to know the way he should create an url to get the models).
The root / gets me a number of links, such as:
{
"_links": {
"colors": "/colors",
"years": "/years",
"models": "???" }
}
What should be instead of ???? If there was some kind of template /models?color={color}&year={year}, the dev would have to create the url. Is this OK?
Or there could be a link to list of years on each color got from /colors and then a link to list of models on each year got from /years?color=red, but i'd have to first choose color, then populate years and then populate models. Any idea if i want to have the model dependent on both color and year, not just the year populated from color?
Is it even possible in this situation to make it hateoas-compliant?
I have not heard of HATEOAS before, but based on what I just read about it, it seems that it supposed to return links to where the consumer of the service can go forward in the "state machine".
In your case that would translate to the links being "function calls". The first two (/colors and /years) are functions that take no parameters (and return "something" at this point), while the third is a function call that takes two parameters: one that is a representation of a color, the other a year. For the first two having a simple URL will suffice for the link, but for the third, you need to include the parameter name/type information as well. Something like:
{
"_links": {
"colors": "/colors",
"years": "/years",
"models": {
"url": "/models",
"param1": {"color"}
"param2": {"year"}
}
}
}
Note: you can use the same layout as "models" for "colors" and "years" as well.
At this point the client knows what the URL to access the functions are and what the parameter (if any) names are to be passed to the function.
One more thing is missing: types. Although you could just use "string", it will not be obvious that the "color" parameter is actually a value from what "/colors" returns. You can be introducing a "type" Color that describes a color (and any functions that operate on a color: give a displayable name, HTML color code, etc.)
The "beefed up" signature becomes:
{
"_links": {
"colors": {
"url": "/colors",
"return": "/type/List?type=/type/Color"
},
"years": {
"url": "/years",
"return": "/type/List?type=/type/Integer"
},
"models": {
"url": "/models",
"param1": {
"name": "color",
"type": "/type/Color"
},
"param2": {
"name": "year",
"type": "/type/Integer"
}
"return": "/type/List?type=/type/Model"
}
}
}
Note: the path "/type" is used just to separate the types from functions, but is not necessary.
This will interchangeably and discoverably describe the functions, what parameters they take, and what values they are returning, so you can use the right value at the right place.
Of course implementing this on the service end will not be easy (especially with parameterized types, like "/type/List" -- think Generics in Java or templates in C++), but this is the most "safe" and "portable" way you can describe your interface to your clients.