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"
}
.....
]
Related
I am creating a strict validator for a complex JSON file and want to re-use various definitions in order to keep the schema manageable and easier to update.
According to the documentation it is necessary to use allOf to extend a definition to add more properties. This is exactly what I've done, but I find that without use of additionalProperties set to false validation doesn't prevent arbitrary other properties being added.
The following massively cut-down schema demonstrates what I'm doing:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/schema/2021/02/example.json",
"description": "This schema demonstrates how VSCode's JSON schema mechanism fails with allOf used to extend a definition",
"definitions": {
"valueProvider": {
"type": "object",
"properties": {
"example": {
"type": "string"
},
"alternative": {
"type": "string"
}
},
"oneOf": [
{
"required": [
"example"
]
},
{
"required": [
"alternative"
]
}
]
},
"selector": {
"type": "object",
"allOf": [
{
"$ref": "#/definitions/valueProvider"
},
{
"required": [
"operator",
"value"
],
"properties": {
"operator": {
"type": "string",
"enum": [
"IsNull",
"Equals",
"NotEquals",
"Greater",
"GreaterOrEquals",
"Less",
"LessOrEquals"
]
},
"value": {
"type": "string"
}
}
}
],
"additionalProperties": false
}
},
"properties": {
"show": {
"properties": {
"name": {
"type": "string"
},
"selector": {
"description": "This property does not function correctly in VSCode",
"allOf": [
{
"$ref": "#/definitions/selector"
},
{
"additionalProperties": false
}
]
}
},
"additionalProperties": false
}
}
}
This works a treat in IntelliJ IDEA's JSON editor (2020.3.2 ultimate edition) when editing JSON against this schema (using a schema mapping). For example, the file ex-fail.json's content of:
{
"show": {
"name": "a",
"selector": {
"example": "a",
"operator": "IsNull",
"value": "false",
"d": "a"
}
}
}
Is correctly validated, simply highlighting "d" as not allowed, thus:
However, when I use the very same schema and JSON file with VSCode (1.53.2) with vanilla configuration (except for a schema mapping) VSCode erroneously marks "example", "operator", "value" and "d" as not allowed. It looks like this in the VSCode editor:
If I remove the additionalProperties definition from the show.selector property, both IDEA and VSCode indicate that all is well, including allowing the "d" property - in doing this I can simplify that property definition to:
"selector": {
"description": "This property does not function correctly in VSCode",
"$ref": "#/definitions/selector"
}
What can I do to the schema to support both IDEA and VSCode whilst disallowing additional properties where they should not appear?
PS: The schema mapping in VSCode is simply along the lines of:
{
"json.schemas": [
{
"fileMatch": [
"*/config/ex-*.json"
],
"url": "file:///C:/my/path/to/example-schema.json"
}
]
}
You cannot do what you ask with JSON Schema draft-07 or prior.
The reason is, when $ref is used in a schema object, all other properties MUST be ignored.
An object schema with a "$ref" property MUST be interpreted as a
"$ref" reference. The value of the "$ref" property MUST be a URI
Reference. Resolved against the current URI base, it identifies the
URI of a schema to use. All other properties in a "$ref" object MUST
be ignored.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-01#section-8.3
We changed this to not be the case for draft 2019-09.
It sounds like VSCode is merging the properties in applicators upwards to the nearest schema object (which is wrong), and IntelliJ IDEA is doing something similar but in a different way (which is also wrong).
The correct validation result for your schema and instance is VALID. See the live demo here: https://jsonschema.dev/s/C6ent
additionalProperties relies on the values of properties and patternProperties within the SAME schema object. It cannot "see through" applicators such as $ref and allOf.
For draft 2019-09, we added unevaluatedProperties, which CAN "see through" applicator keywords (although it's a little more complex than that).
Update:
After reviewing your update, sadly the same is still true.
One approach makes it sort of possible but involves some duplication, and only works when you control the schemas you are referencing.
You would need to redefine your selector property like this...
"selector": {
"description": "This property did not function correctly in VSCode",
"allOf": [
{
"$ref": "#/definitions/selector"
},
{
"properties": {
"operator": true,
"value": true,
"example": true,
"alternative": true
},
"additionalProperties": false
}
]
}
The values of a property object are schema values, and booleans are valid schemas. You don't need (or want to) deal with their validation here, only say these are the allowed ones, followed by no additionalProperties.
You'll also need to remove the additionalProperties: false from your definition of selector, as that is preventing ALL properties (which I now guess is why you saw that issue in one of the editors).
It involves some duplication, but is the only way I'm aware of that you can do this for draft-07 or previous. As I said, not a problem for draft 2019-09 or above due to new kewords.
additionalProperties is problematic because it depends on the properties and patternProperties. The result is that "additionalProperties": false effectively blocks schema composition. #Relequestual showed one alternative approach, here is another approach that is a little less verbose, but still requires duplication of property names.
draft-06 and up
{
"allOf": [{ "$ref": "#/definitions/base" }],
"properties": {
"bar": { "type": "number" }
},
"propertyNames": { "enum": ["foo", "bar"] },
"definitions": {
"base": {
"properties": {
"foo": { "type": "string" }
}
}
}
}
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.
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
I'm getting an error while I'm trying to navigate to another page in the sapui5 application. I'm trying to figure out what I am doing wrong. The directory Structure of my application is as below:
In manifest file
"routes": [{
"pattern": "",
"name": "appHome",
"target": "home"
}
, {
"pattern": "Course/{courseId}",
"name": "course",
"target": "course"
}],
"targets": {
"home": {
"viewName": "Home",
"viewLevel" : 1
},
"notFound": {
"viewName": "NotFound",
"transition": "show"
} ,
"course": {
"viewPath": "dlesDLESdashboard.view.Course",
"viewName": "CourseDetail",
"viewLevel" : 2
}
}
},
When I click on my navigate button I am triggering this event by default I'm giving static ID later I'll change.
handleCourseClick : function(oEvent){
this.getRouter().navTo("course",{courseId :"222222"});},
I'm not sure this information is good enough to find out my error or not.
The Error is that when I click on the tile I'm getting this error instead of navigating to my course detail page.
Check your controller, there might be something wrong with your view and controller connection. check namespace, name of controller etc and verify it.
sap.ui.define([
"sap/ui/model/json/JSONModel",
"locations/util/Utils",
"locations/controller/BaseController"
], function(BaseController, JSONModel, Utils) {
I declared these in the wrong order, and caused the same problem.
I have a the following function in my controller file:
handleNavTo : function (oEvent){
var page = oEvent.getSource().data("navToPage");
var router = sap.ui.core.UIComponent.getRouterFor(this);
router.navTo(page);
}
So I don't have to write out a new function for each link, I'm using a data attribute in an XML view to pass in the page I want to navigate to, like this:
<StandardTile
title="{i18n>tileEmployees}"
press="handleNavTo"
data:navToPage="employees"
icon="sap-icon://employee"/>
<StandardTile
title="{i18n>tileProducts}"
press="handleNavTo"
data:navToPage="products"
icon="sap-icon://product"/>
I have the routing configured in a manifest.json file:
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "testApp.view",
"controlId": "app",
"controlAggregation": "pages",
"transition": "slide",
"bypassed": {
"target": "notFound"
}
},
"routes": [
{
"pattern": "",
"name": "appHome",
"target": "home"
},
{
"pattern": "products",
"name:": "products",
"target": "products"
},
{
"pattern": "employees",
"name": "employees",
"target": "employees"
}
],
"targets": {
"home": {
"viewName": "Home",
"viewLevel": 1
},
"notFound": {
"viewName": "NotFound",
"transition": "flip"
},
"products": {
"viewPath": "testApp.view.products",
"viewName": "ProductsSplitView",
"viewType": "JS",
"viewLevel": 2
},
"employees": {
"viewPath": "testApp.view.employees",
"viewName": "EmployeesSplitView",
"viewType": "JS",
"viewLevel": 2
}
}
My problem is that clicking on the tiles only works for the Employees page. I know the routing is configured correctly for the products page as I can type in the url in the address bar and it brings up the page: mydomain.com/#/products.
I get no errors, it just seems to silently fail. the data attribute value is being called correctly, if I console.log(page) in the controller function I get the correct value, so this has be stumped.
Any help would be appreciated.
i would guess that it does not find the route by name because you have a typo in the route config: "name:": "products", should be "name": "products",