Why Is "target" an Array? - sapui5

I have the following route definition:
"routes": [{
"name": "overview",
"pattern": "",
"target": [
"overview"
]
}, {
"name": "customers",
"pattern": "/customers",
"target": [
"customers"
]
}, {
"name": "customer",
"pattern": "/customer/{id}",
"target": [
"customer"
]
}],
Why does the target property expect an array?

The value of the target property can be an array but it doesn't have to be, as stated in the API reference of sap.ui.core.Route:
The reason why it can await an array at all, is to support displaying multiple view (target) instances at once when navigating to a single route / navigating based on a certain hash value.
Source: Routing and Navigation
Example: The app is based on the Flexible Column Layout (formerly "Split-Screen" layout with sap.m.SplitApp) and the user visits it via a deep link having the hash value already e.g. #/Objects/ObjectID_14.
Source code
In this case, if only a single target name were assigned to the target property, only one of the views would have been able to be displayed. The target property can, however, contain multiple target names which will be then resolved and put based on the controlAggregation accordingly.
"routes": [
{
"name": "masterDetail",
"pattern": "Objects/{objectId}",
"target": [
"master",
"detail"
]
}
],
"targets": {
"master": {
"name": "Master",
"controlAggregation": "beginColumnPages"
},
"detail": {
"name": "Detail",
"controlAggregation": "midColumnPages"
}
}
To learn more about routing, please follow these steps: https://ui5.sap.com/#/topic/1b6dcd39a6a74f528b27ddb22f15af0d

Because a route could have multiple targets. This is the equivalent of the former subroutes.
By using multiple targets for a single route you can update different areas of your application at the same time resp. based on the same routing pattern.
Think of a SplitApp. If you want to change as well Master and Detail view based on routing you can define both of them as targets of the same route.
Find more info in the docs: https://sapui5.hana.ondemand.com/#/topic/b01840ec42ef48e6bfd2bc12612f501f

Related

Why it does not show two columns?

I am trying to use Flexible Column Layout on my app and I have trouble with the routing. However it does not show the expected result on the screen.
The routing is defined as follows:
"routing": {
"config": {
"routerClass": "sap.f.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "com.example.RequestAccess.view",
"controlId": "fcl",
"transition": "slide",
"bypassed": {}
},
"routes": [{
"pattern": "jobprofile",
"name": "jobprofile",
"target": [
"JobProfileSelector",
"JobProfileOrder"
]
}, {
"pattern": ":layout:",
"name": "authorize",
"target": [
"Authorization"
]
}],
"targets": {
"Authorization": {
"viewName": "Authorization",
"controlAggregation": "beginColumnPages"
},
"JobProfileOrder": {
"viewName": "JobProfileOrder",
"controlAggregation": "midColumnPages"
},
"JobProfileSelector": {
"viewName": "JobProfileSelector",
"controlAggregation": "beginColumnPages"
}
}
}
},
when I do the call
var oRouter = this._getRouter();
oRouter.navTo("jobprofile");
it shows one column layout instead two columns. I expect to be two columns, because I have defined:
"pattern": "jobprofile",
"name": "jobprofile",
"target": [
"JobProfileSelector",
"JobProfileOrder"
]
Two targets for the path /jobprofile.
I expect, that the app should show like this:
What am I doing wrong?
Update
I have created an example app https://github.com/softshipper/fclpoc.
Click on Go to jobprofile
and you will redirect to page /jobprofile path. Here I expect, that it is going to show me Second and Third view next to each other, like master detail view.
You have to adjust property layout of your FlexibleColumnLayout in order to have 1, 2 or 3 columns. Default is 1.
In your root view, you already have a binding on this property, which is a good idea.
<FlexibleColumnLayout id="fcl"
stateChange="onStateChanged"
layout="{/layout}"
backgroundDesign="Solid">
</FlexibleColumnLayout>
However, you are not calling function _updateLayout from the App.controller.js anywhere.
I suggest refactoring this controller to adjust the layout based on the active route.

Routing to the same `pattern` but with different `args` ,`name` and `targets`

What I am trying to do is , the pattern in the routing is same but the target and name are different as:
"routes":[
{
"pattern": "spec/{Name}/{Action}", //{Name}=ABC {Action}=add
"name": "ABCSpecificationNew",
"target": "ABCSpecificationNew"
},
{
"pattern": "spec/{Name}/{Action}", //{Name}=ABCPlus {Action}=add
"name": "ABCPlusSpecificationNew",
"target": "ABCPlusSpecificationNew"
},
.....
],
I was trying to pass this way for Name,
var routerPath=Name+"SpecificationNew"; //getting `Name` by `Id` from `view`//
this.getRouter().navTo(routerPath,
{
Action: "Add", Name:Name
});
So from above, Name and Action are passed to pattern
"targets":[
"ABCSpecificationNew": {
"viewId": "abc",
"viewPath": "com.sample.view.employee",
"viewName": "ABCSpecificationConfigurationNew",
"parent": "home",
"controlId": "parentNavContainer",
"controlAggregation": "pages"
},
"ABCPlusSpecificationNew": {
"viewId": "abcplus",
"viewPath": "com.sample.view.employee",
"viewName": "ABCplusSpecificationConfigurationNew",
"parent": "home",
"controlId": "parentNavContainer",
"controlAggregation": "pages"
},
.....
]
Now when I am trying to hit the pattern ---> spec/ABCPlus/add
It is routing to ABCSpecificationNew instead of ABCPlusSpecificationNew,
To my knowledge, it should match the target and route to the same ,
but this is not happening in my case.
Even though pattern here are different for both cases, it is routing to the first route.
I have no idea why this is happening , every part in the view and controller I have confirmed with no mistakes and it must have happened only in routing,
Is there a way to achieve this , any help is appreciated..TIA
The curly bracket is a placeholder. The matching is solely based on the pattern. Therefore ANYTHING will match {Name}. Be it ABC, ABCPlus, DEF, CHEESE_NUGGETS, you name it.
When matching, the router will use the first target it finds. In your case ABCSpecificationNew.
If you only want to support exactly the two names ABC and ABCPlus I suggest the following:
"routes": [
{
"pattern": "spec/ABC/{Action}",
"name": "ABCSpecificationNew",
"target": "ABCSpecificationNew"
}, {
"pattern": "spec/ABCPlus/{Action}",
"name": "ABCPlusSpecificationNew",
"target": "ABCPlusSpecificationNew"
},
.....
],
Also if your action is always add (and the name and target of your route contain the word New it might make sense to hardcode the action also in your route definition, e.g. "pattern": "spec/ABCPlus/add".
Because right now someone could type in spec/ABC/delete and would also land in ABCSpecificationNew.
As per the routing is consider same patterns will not make any sense. So my suggestion for you is to use a single pattern like "pattern": "spec/{Name}/{Action}" with an extra parameter which will help you to decide the type of view you want to render ABCSpecificationConfigurationNew OR ABCplusSpecificationConfigurationNew.
Pattern
"pattern": "spec/{Name}/{Action}/{Type}"
"routes":[
{
"pattern": "spec/{Name}/{Action}/{Type}", //{Name}=ABC/ABCPlus - {Action}=add - {Type}= ABCSpecificationConfigurationNew OR ABCplusSpecificationConfigurationNew
"name": "ABCSpecificationNew",
"target": "ABCSpecificationNew"
}
.....
],
"targets":[
"ABCSpecificationNew": {
"viewId": "XYZ",
"viewPath": "com.sample.view.employee",
"viewName": "ABCSpecificationConfiguration", //single view to render the content based on the parameter Type
"parent": "home",
"controlId": "parentNavContainer",
"controlAggregation": "pages"
}
.....
]

identify new words as intents in rasa nlu

Have been using rasa nlu to classify intents and entities for my chatbot. Everything works as expected (with extensive training) but with entities, it seems to predict the value based on the exact position and length of the word. This is fine for a scenario where the entities are limited. But when the bot needs to identify a word (which has a different length and not trained yet, for example a new name), it's failing to detect. Is there a way wherein I can make rasa identify the entities based on the relative position of the word or better yet, insert a list of words that becomes the domain specific for the entity to find a match with (like phrase list in LUIS)?
{"q":"i want to buy a Casio SX56"}
{
"project": "default",
"entities": [
{
"extractor": "ner_crf",
"confidence": 0.7043648832678735,
"end": 26,
"value": "Casio SX56",
"entity": "watch",
"start": 16
}
],
"intent": {
"confidence": 0.8835646513829762,
"name": "buy_watch"
},
"text": "i want to buy a Casio SX56",
"model": "model_20180522-165141",
"intent_ranking": [
{
"confidence": 0.8835646513829762,
"name": "buy_watch"
},
{
"confidence": 0.07072182459497935,
"name": "greet"
}
]
}
But if Casio SX56 gets replaced with Citizen M1:
{"q":"i want to buy a Citizen M1"}
{
"project": "default",
"intent": {
"confidence": 0.8710909096729019,
"name": "buy_watch"
},
"text": "i want to buy a Citizen M1",
"model": "model_20180522-165141",
"intent_ranking": [
{
"confidence": 0.8710909096729019,
"name": "buy_watch"
},
{
"confidence": 0.07355588750895545,
"name": "greet"
}
]
}
Thank you!
Make sure you actually added each entity value training examples before training it with rasa_nlu.
--- For successful entity extraction we need to create at least 2 or more contextual training data ---
add this eg. in rasa_nlu training data if it's not extracting properly
"text": "i want to buy a Citizen M1",
"model": "model_20180522-165141",
"intent_ranking": [
{
"confidence": 0.8710909096729019,
"name": "buy_watch"
},
{
"confidence": 0.07355588750895545,
"name": "greet"
}
]
entity extraction with phrase matching does work in rasa_nlu try it with spacy_sklearn backend pipeline
The feature I was looking for is phrase matcher which would allow me to add a list of possible entities to the training model. This way, if any new name pops up, we can simply add the name to the phrase list and the model would be able to identify it with all possible utterances. Though this is still in development and should be added to the master soon: https://github.com/RasaHQ/rasa_nlu/pull/822

Access OData services from two different system in SAP Web IDE

I have two OData services on two different systems, for which I have added destinations in HCP and entries in neo-aap.json file.
{
"path": "/sap/opu/odata",
"target": {
"type": "destination",
"name": "ABC",
"entryPath": "/sap/opu/odata"
},
"description": "ABC"
}, {
"path": "/sap/opu/odata",
"target": {
"type": "destination",
"name": "XYZ",
"entryPath": "/sap/opu/odata"
},
"description": "XYZ"
}
With this, I'm able to access only one system's service i.e. OData service which is on ABC. When app loads app tries to load hit metadata for 2nd OData service as well in ABC which is obviously not there, hence fails.
How do I access the OData service on XYZ system?
If the 'path' is the same, only the first one will be matched. Set different paths for your destinations.
The 'path' property in the neo-app.json is just an alias for your destinations. With your config, this means, whenever in your app, you request something from '/sap/opu/odata/... ' the application will overwrite this part of the path with the URL you configured in the Destination.
Just make something like this:
{
"path": "/ABC/sap/opu/odata",
"target": {
"type": "destination",
"name": "ABC",
"entryPath": "/sap/opu/odata"
},
"description": "ABC"
}, {
"path": "/XYZ/sap/opu/odata",
"target": {
"type": "destination",
"name": "XYZ",
"entryPath": "/sap/opu/odata"
},
"description": "XYZ"
}
And then make sure you use "/ABC/sap/opu/odata" or "/XYZ/sap/opu/odata" whenever you set your model data sources.
This, from my perspective, is a bug.
The key used for locating the destination is the "path" value so you will always hit the first destination.
You can resolve this by changing the path from /sap/opu/odata to /sap/opu/odata1
You then edit your dataSources in your manifest.json: adjust the "uri" with the adjusted path on any models you are trying to point to the 2nd path.
I have written on this here and am busy trying to get SAP to change this behaviour.

Multiselect in Impresspages Plugin Options

How may I use a multiselect field in the Impresspages Plugin options. Something like this:
{
"label": "Social Nets",
"name": "socialNets",
"type": "select",
"multiple": "multiple",
"default": "",
"values": ["", "facebook", "twitter", "pintrest"]
}
Of course, the field above "multiple" doesn't work in this code snip. So, how to implement it in the plugin options json file?
You can use "Checkboxes" field type
"options": [
{
"label": "XXX",
"name": "xxx",
"type": "Checkboxes",
"values": ["option1", "option2", "options3", "option4"]
}
]
There is no such option implemented in the core of the system. Meaning, there's no such field type as 'multiselect'. You can check how other fields are implemented and extend the core, create pull-request and we'll add it in next release.