SparkViewEngine: Using Url.Content in global variable in Application.Spark - asp.net-mvc

I am using ASP.NET MVC 2 with SparkViewEngine 1.1 and I get the error message An object reference is required for the non-static field, method, or property 'Spark.Web.Mvc.SparkView.Url.get' when I use the following code in the Application.spark view file
<global baseImagePath='Url.Content(Context,"~/Content/_images")' type="string" />
What I am trying to accomplish is basically define a base image path as a global variable that can be referenced in the page templates.
For example, in Home/Index.spark, which uses the master Application.spark, I would have the following code snippet in the view
<img src="${baseImagePath}" alt="..." />
As a workaround, I can set a hard-coded value when I set baseImagePath by doing <global baseImagePath='"~/Content/_images"' type="string" />, but I want to also be able to resolve the "~" before hand.
Any suggestions?
Thank you!
Edit
I am adding my solution here per Rob's suggestions
In Shared/_global.spark, I added <use namespace="System.Web" /> so that I have access to the System.Web namespace.
In Shared/Application.spark, I added
<global baseImagePath='VirtualPathUtility.ToAbsolute("~/Content/_images")' type="string" />

The problem here is that Url.Content(... is accessing the UrlHelper class in System.Web.Mvc from the SparkView instance. The problem is that when the Application.spark is being parsed for globals, you don't yet have an instance of a view because global variables are defined before the generated view class is instantiated. Therefore accessing and instance variable like Url from the view is not possible.
From the looks of it though, you're just trying to get an absolute path from a relative one. For this you could potentially just use the static VirtualPathUtility class from System.Web.
There are a number of methods on there like ToAbsolute(...) that make life easier. Alternatively, you could get it from the HttpContext.Current.Server.MapPath(...) method if you have the current context.
Hope that helps,
All the best,
Rob G

Related

SAPUI5 - how to set value to input parameter in binding dynamically

In my XSOData service I have an entity based on calculation view with input parameters. I can to set these parameters as constants in my XML view, i.e.
<List items="{dicts>/AncParams(p_dict_name='GROUPS',p_rec_id=2)/Results}" >
<StandardListItem
title="{dicts>NAME}"
/>
</List>
and it will work fine.
But how I can set parameters p_dict_name and p_rec_id dynamically? I tried to use expression bindings to get values for parameters from another model (something like this: <List items="{= ${dicts>/AncParams(p_dict_name='GROUPS',p_rec_id=${DictUIProps>/parentId})/Results} }" >) but with no luck. As I understand, expression bindings won't work. Is there any other way?
As far as I'm aware you can't do the aggregation binding dynamically through XML. At least not in the versions I have used and I have to admit I haven't re-checked in a while. The string never gets interpreted for inner bindings before it's applied to the model.
The way I do this is through the controller:
<List id="myList" />
and in your controller (onBeforeRendering or onPatternMatched or wherever your model and view are known to the controller):
this.getView().byId('myList').bindItems({
model: 'dicts',
path: `{/AncParams(p_dict_name='${p_dict_name}',p_rec_id=${p_rec_id})/Results}`,
template: new sap.m.StandardListItem({
title: '{dicts>NAME}'
})
});
you can use the getModel('dicts').createKey function to generate the path name which is a little cleaner I suppose.
This is the way to apply dynamic filters as well, In case you ever build those.

using <set> tag in grails

I am new to grails. I came across a set tag which we can use in gsp pages itself to set the values which is similar to setting model from the controller.
<g:set var="home" value="something" />
so that when we write ${home} it outputs "something".
Is there any way to set the value in sessions in gsp pages itself and not from controller using set tag?
Yes you can do it in gsp pages as well. You just have to include an extra attribute scope to indicate which scopes(session, flash, page and request) you are setting the value to.
<g:set var="home" value="something" scope="session" />
If you do not include the scope option then it defaults to page.
To display the the value you just have to write ${session.home} or ${request.home} or simply ${home} for request scope. Hope this helps.
For more : https://grails.github.io/grails-doc/3.0.x/ref/Tags/set.html
Well! above answer suffices the need. Just wanted to add one more thing that gsp pages comprises of jsp internally and hence all the 9 implict objects are available on gsp pages as well.
request HttpServletRequest object
response HttpServletResponse object
out PrintWriter object used to send output to the client.
session HttpSession object
application ServletContext object associated with application context.
config ServletConfig object associated with the page.
pageContext server-specific features JspWriters.
page synonym for this
Exception handling exceptions and error page redirects.An instance of javax.servlet.jsp.JspException
You could at any point of time access these in your gsp pages.
More you can read from this.
Hope it helps!

How can I pre-populate a hidden form field in grails?

I have just gotten started with Grails and I have a very basic application running. I want to pre-populate a hidden form field with a random string.
What is the best way to do this? I have looked at the taglib but I am not sure what the best practice is for this sort of thing. Should I create a class in the src/java or src/groovy folder or is there a better way to get this done?
Lastly, and I know this is a very basic question, but if I do create a class or taglib, how exactly is that called from within the .gsp page?
Thanks!
If your action looks like this
def create() { [orgInstance: new Org(params)] }
it means that a new Org object is passed to your view which can be referenced as orgInstance
Since the model [orgInstance: new Org(params)] is a map, you can simply add another parameter:
def create() { [orgInstance: new Org(params), hiddenValue: 'something random'] }
This can be used in your .gsp in the following way:
<input type="hidden" name="test" value="${hiddenValue}" />
Regarding your other question: a custom taglib is used in the same way as the other Grails-Tags: <g:myTag ...>...</g:myTag> . You can change the namespacegto whatever you like -g` is the default. See the documentation for more details: http://grails.org/doc/latest/ref/Tag%20Libraries/Usage.html

Can I get Intellij Idea 10.5 to do code completion on model variables in a shared GSP template?

*Edit* I didn't know about 'Add Dynamic Property' feature of Idea, that is exactly what I wanted. Thanks Sergey
I love the fact how Intelli-J recognizes the type of variables put into the model from a common controller and allows autocomplete right in the GSP.
For example if I have a controller method
def mymethod = {
MyDomain myDomainInstance =
.... logic ...
[myDomainInstance: myDomainInstance]
}
In my corresponding mymethod.gsp, Intelli-J will autocomplete methods on ${myDomainInstance} from the MyDomain bean.
However consider a shared template that uses the same domain class and could be rendered via
<g:render template="/shared/somesharedtemplate" model="['myDomainInstance': myDomainInstance]">
When I am editing /shared/_somesharedtemplate.gsp, ${myDomainInstance} is not recognized as something Intelli-J knows about (but of course works fine when Grails runs). Is there any declaration or anything I can add to the GSP to hint it?
Try to remove quotes around variable name in value of 'model' attribute. IDEA does not recognize model variable defined inside quotes. It's a bug: http://youtrack.jetbrains.net/issue/IDEA-80041.
Also you can add a dynamic property 'myDomainInstance' for page _somesharedtemplate.gsp . Press Alt+Enter on unrecognized reference then select 'Add Dynamic Property 'myDomainInstance'' intention.

Grails: Supplying Data to a Global UI Element

Please pardon this newbie question...
In Grails, if I want a partial to be embedded in a layout so that it appears globally, which requires live data, let's say a list of categories, where is the best place to pull the category data to feed it into the view?
I realize this is a very basic question, but I haven't seen this covered in any tutorials yet.
I started this as a comment to Bill James's answer but I figured it might be longer. Bill suggeseted using groovy code inside ${} to make the template (called partial in Rails) work globally:
<g:each in="${ Category.findAll() }" var="cat" />
But, you should not just add code if you dont feel like it might mess up your tidy xml/html. You can always put it in a closure inside a TagLib and thus make it a Tag. The closure must have no parameters, or an 'attr' parameter, or an 'attr' and 'body' parameters but other signatures are invalid.
class CustomTagLib {
static namespace = 'cus'
def categories = { attr, body ->
g.each( in: Category.findAll(), var: attr?.var ?: 'categories' )
}
}
Then you can use that tag into the template with the namespace you chose:
<cus:categories />
Personally I prefer using tags since most of the time it is a reusable code, so it's better for not violating the DRY principle.
You want to put it in grails-app\views\layouts\main.gsp. That's the default layout that most generated code (and likely most examples that you'll see) will use.
Check out the sitemesh section of the grails documentation.
I think you're trying to ask... "How do I feed the category data to the view when I don't know which action caused the page to render, so the action can't add the data to the model?" If that's so, you can use Groovy code directly in the ${} block, such as:
<g:each in="${ Category.findAll() }" var="cat" />
Note that findAll is added to every Model class, and can be called statically (via the classname, not an instance).
Hope this helps

Resources