What is the difference between sap.ui.core.routing.Router.navTo() and sap.m.routing.Targets.display()? - sapui5

Let’s say we I have one route and one target:
"routes": [{
"pattern": "modify",
"name": "modify",
"target": [
"master",
"modify"
]
}],
"targets": {
"modify": {
"viewName": "Modify",
"viewId": "modify",
"viewLevel": 2
}
}
So I can access the route by this.getRouter().navTo("modify"), meanwhile I can access the target by this.getRouter().getTargets().display("modify"). Both API can carry parameter by the second argument. It seems to achieve the same effect.
I can access target without defining a route for it. So I did not quite understand why I need a route?
Ref: sap.m.routing.Targets and
sap.ui.core.routing.Router

display displays the target view without changing the hash value in contrast to navTo.
You can find more information in the tutorial "Display a Target Without Changing the Hash".
Both API can carry parameter by the second argument. It seems to achieve the same effect.
The data in display method is for the display event handler. When the event is fired, the handler carries the data we passed earlier.
The parameter map we can pass to navTo is mandatory if the pattern actually awaits a parameter, e.g. if we've defined the pattern like this initially: "pattern": "modify/{id}". Check out "Navigate to Routes with Mandatory Parameters".

Just complement Boghyon's answer:
Route pattern is defined in Router, and hash is set in Router. That's the main difference.BTW, UI5 uses crossroads and hasher to help implementing router.
navTo() in sap.m.routing.Router is borrowed from sap.ui.core.routing.Router
display() in sap.m.routing.Targets is borrowed from sap.ui.core.routing.Targets
in _routeMatched of Route, oRouter._oTargets._display is called. So _display is called in both Router and Targets.
The parameter they use are different.navTo use Route name, and display use Target name. Sometimes they are defined the same.
onToPage2 : function () {
// this.getOwnerComponent().getRouter().navTo("pageRoute2");
this.getOwnerComponent().getRouter().getTargets().display("pageTarget2");
},
onToPage1 : function () {
this.getOwnerComponent().getRouter().navTo("pageRoute1");
// this.getOwnerComponent().getRouter().getTargets().display("pageTarget1");
}

Related

Variable does not expand in transformation

I am working on a VS code extension for a custom language. This contains a snippet that allows the user to create a function with parameters and start to set up some documentation inside the function. The way I am achieving this is to use variable transforms on the parameter variable (${2}) using some matching tricks to extract each individual parameter and data type. In this simpler example, each parameter name will be on its own line inside a block comment.
"function": {
"prefix": "func",
"body": [
"function ${1:functionName}(${2:params})",
"${2/([^,]+), *|([^,]+$)/\t${BLOCK_COMMENT_START} ${1}${2} ${BLOCK_COMMENT_END}\n/g}",
"end"
]
}, ...
The expected output is this:
function functionName(hello,world)
{ hello }
{ world }
end
The actual output is this:
function functionName(hello,world)
${BLOCK_COMMENT_START} hello ${BLOCK_COMMENT_END}
${BLOCK_COMMENT_START} world ${BLOCK_COMMENT_END}
end
The issue is that ${BLOCK_COMMENT_START} and _END do not expand inside the transform. I can easily get around this issue by hardcoding the curly braces in the snippet, but I would prefer to find a way where I do not have to do that.
"body": [
"function ${1:functionName}(${2:params})",
"${2/([^,]+), *|([^,]+$)/\t{ ${1}${2} }\n/g}",
"end"
]
Is there a way that I can have a variable expand in the transform?

Add tasks to tasks.json for users of a vscode extension

I am writing a vscode extention for a specification language. I would like to provide the users of the plugin with a specific task. The task could be made available using tasks.json.
Is there a way to add tasks to the tasks.json of a user that uses that extension?
The documentation didn't help me here either. When you provide tasks through the extension there is the TaskProvider API. The example doesn't go into much detail about how these tasks are created though, compared to the classical tasks.json approach.
In your package.json you need to define the types of tasks this extension contributes. This has nothing to do with the type in tasks.json. It's rather a freeform string. If you need custom problem matchers you also need to define theme here.
"contributes": {
"taskDefinitions": [
{
"type": "mytask"
}
],
"problemMatchers": [
{
"name": "mywarnings",
"base": "$gcc",
"fileLocation": [
"relative",
"/"
]
}
]
},
In extension.ts you need to provide the tasks. Say we have an array of vscode.Task in tasks you can do:
vscode.tasks.registerTaskProvider('mytask', {
provideTasks: () => {
return tasks;
},
resolveTask(_task: vscode.Task): vscode.Task | undefined {
// as far as I can see from the documentation this just needs to return undefined.
return undefined;
}
});
If you want to create a shell task you need the following:
new vscode.Task (
{type: 'shell'}, // this is the same type as in tasks.json
ws, // The workspace folder
'name', // how you name the task
'MyTask', // Shows up as MyTask: name
new vscode.ShellExecution(command),
["mywarnings"] // list of problem matchers (can use $gcc or other pre-built matchers, or the ones defined in package.json)
);
I hope this helps. The bigges issue I see is the overloading of various names (like type), and that the format in tasks.json is completely different to the way tasks are built with TaskProvider API.

Provide check in RHS for existence of a field inside pojo in drools

I am new to drools.
I want to check in RHS that if a field is present in POJO or not.
{
"category": [
{
"nlp": [
{
"mainCategory": "Politics"
}
],
"crawler": [
{
"isNLP": true,
"mainCategory": "Politics"
}
]
}
]
}
This is list of the pojo that are generated
EsRootDoc.java
Crawler.java
Nlp.java
EsRootDoc is the main class which have methods and fields.`when
$RHSmap1:EsRootDoc()
and
$map1:EsRootDoc($categorylist1:category)
$category2:Category($nlplist2:nlp) from $categorylist1
$nlp2:Nlp(mainCategory=="politics") from $nlplist2
then
$RHSmap1.setEvent("fight");
end`
This is giving me following error
[Error: unable to resolve method using strict-mode: com.orkash.EnrichmentService.EnrichmentController.tempJsonToClass.EsRootDoc.setEvent(java.lang.String)]
[Near : {... $RHSmap1.setEvent("fight"); ....}]
I need to provide a check in RHS :- that if EsRootDoc has a field event or not
There is nothing in Drools (as far as I know) that allows you to do what you are looking for. The RHS of a rule is - almost- pure Java. The basic rule then is: if it can't be done in Java, it can't be done in the RHS of a rule in Drools.
The good news is that what you are trying to do can be achieved in Java using reflection. My recommendation would be for you to create a helper class that uses reflection to set the value of an attribute in an object if that attribute exists. Your rules then would look like this:
rule 'Some Rule'
when
$RHSmap1:EsRootDoc()
$map1:EsRootDoc($categorylist1:category)
$category2:Category($nlplist2:nlp) from $categorylist1
$nlp2:Nlp(mainCategory=="politics") from $nlplist2
then
Helper.setAttribute($RHSmap1, "event", "fight");
end
Hope it helps,

How to get property of a JSONModel in my Controller? [duplicate]

This question already has answers here:
How to get model on onInit?
(2 answers)
Closed 4 years ago.
I need to retrieve the property of my JSONModel in my controller.
The scenario is as follows:
I have a "questionnaire" model (questionnaire.json) which contains questions and answers. Then I have a controller (App.controller.js).
In this controller, I have created one more model in onInit with the name "currentQuestion" because I need to implement a scenario where the next question should be loaded when the user clicks on the next button.
I am trying to get the property of my "questionnaire" model but I am facing an error:
Cannot read property of 'getProperty' of undefined.
You can see the model data and my controller here:
questionnaire.json
{
"data": [{
"question": "Which pet do you like from the following?",
"answers": ["Cats", "Rabbits", "Dogs", "Hamsters"],
"correct": 1
}, {
"question": "Which pet do you prefer from the following?",
"answers": ["Cats", "Dogs"],
"correct": 1
}, {
"question": "What food brand does your pet eat?",
"answers": ["Pedigree", "Catfood", "Rabbitfood", "HamstersFood"],
"correct": 1
}]
}
App.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel"
], function(Controller, JSONModel){
Controller.extend("opensap.onlinequestionnaire.controller.App", {
onInit: function() {
this.questionSetUp();
this.getView().setModel(new JSONModel({
index: false,
question: {}
}), "currentQuestion");
var oCurrentQuestionModel = this.getView().getModel("currentQuestion");
var oQuestionModel = this.getView().getModel("questionnaire");
var iCurrentIndex = oCurrentQuestionModel.getProperty("/index");
var oQuestion = oQuestionModel.getProperty("/data/0/question");
console.log(oQuestion);
console.log(iCurrentIndex);
iCurrentIndex = iCurrentIndex ? ++iCurrentIndex : 0;
console.log(iCurrentIndex);
}
});
});
When I try to question property in oQuestion, it throws me the error. How do I get the 0th element's question property's value?
One more thing I was doing wrong was I was trying to get this model in init. [src]
Unfortunately yes. That was actually the main reason why the model was undefined in this case. But not because the model was not loaded.
We know from the documentation that models defined in the app descriptor (manifest.json) are set to the component and that those models get propagated to component's children. Hence, calling view.getModel from any controller should return the model seamlessly because it's set globally on the component. But: Something that is not obvious is that models set on the component cannot be retrieved in onInit of any Controller just by using the corresponding view because the view doesn't know its parent yet in that state. Calling view.getParent in onInit returns null. So the component model "questionnaire" was not propagated to your view yet. As you did it already, such component models can be easily retrieved in onInit by using the component instead of the view: this.getOwnerComponent().getModel("modelName") and the error
Cannot read property of 'getProperty' of undefined
is gone.
the method setModel(oModel, sName?) sets a model to your view. In your code you set a Model with the name "currentQuestion" to the view which contains the data from the questionnaire.json file. You get this model in the variable oCurrentQuestionModel.
Please try to get the property from this model by the following code:
oCurrentQuestionModel.getProperty("/data/0/question");
In your code snippet it is not clear where oQuestionModel is defined.
In your case. I think you should change
var oQuestionModel = this.getView().getModel("questionnaire");
to
var oQuestionModel = this.getView().getModel();
because you did not name your model so that it becomes the default model.

Why is this IgnoreRoute call matching these requests?

I've got a localization httphandler that's running in the context of my ASP.Net MVC2 Content folder (part of what it's doing is compiling .less files that are in /Content/css). My default route for this particular set of requests looks like this:
context.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
context.MapRoute(
"Area_default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = new VirtualDirectoryConstraint("VDirectory1") },
new string[] { "Namespace.One.MVC" }
);
(As an aside - I don't think it's relevant, but just in case - the VirtualDirectoryConstraint rejects matches on this route if the request is not coming from the passed-in application path/virtual directory)
With this configuration a call to http://server.net/VDirectory1/Content/css/LessCompiler.axd fails because there's no ContentController class. All well and good.
When I add
context.Routes.IgnoreRoute("{Content}/{*pathInfo}");
that call succeeds, but subsequent calls to
http://server.net/VDirectory1/Localization/ClientScript/en-US.js
and
http://server.net/VDirectory1/Authorization/ClientScript
fail. Looking at Phil Haack's RouteDebugger tool, those calls are matching the Content IgnoreRoute route:
True {Content}/{*pathInfo} (null) (null) (null)
and are therefore not being routed to the LocalizationController and AuthorizationController, respectively.
Clearly I'm misunderstanding something about how the IgnoreRoute is supposed to be used and why that particular IgnoreRoute is matching those requests. What am I missing?
Shouldn't your IgnoreRoute use Content instead of {Content} ?
context.Routes.IgnoreRoute("Content/{*pathInfo}");
At the moment, {Content} is probably being expanded as a variable to nothing, which makes the pathinfo match everything.