I know how to split the string within a Controller or Domain class.
But i want to split the string inside the GSP.
My string will look like:
ASD25785-T
I want to be able to split this into 2 strings inside the GSP view.
String a = ASD25785
String b = T
Is it possible to do that inside the GSP?
How about something like this:
<%
String[] tokens = "ASD25785-T".split("-")
String b = tokens[0]
String c = tokens[1]
%>
NB. use try catch because you may get ArrayOutofBoundException
It depends if you have a predefind format or you want something generic.
Without try/catch and using the regex find method in String:
<%
String s="ASD25785-T"
String a,b
s.find(/(.+)-(.+)/) { fullMatch, first, second -> [
a=first
b=second
}
%>
If you are certain that there will always be a match, then it is a cute one-liner:
<%
String s="ASD25785-T"
def (a,b) = s.find(/(.+)-(.+)/) { fullMatch, first, second -> [first,second]}
%>
Source:
http://naleid.com/blog/2009/04/07/groovy-161-released-with-new-find-and-findall-regexp-methods-on-string
NB: However, if you want to use it in your view, you should create a tag. Grails taglibs are almost trivial to write, and much better to use in GSP code.
http://grails.github.io/grails-doc/2.4.x/ref/Command%20Line/create-tag-lib.html
http://grails.github.io/grails-doc/latest/guide/single.html#taglibs
Here's a string manipulation taglib
class StringsTaglib {
def split = { attrs, body ->
String input= attrs.input
String regex= attrs.regex
int position= attrs.index as Integer
out << input.split(regex)[position]
}
}
you could then use it like this:
a:<g:split input="ASD25785-T" regex="-" index="0"/>
b:<g:split input="ASD25785-T" regex="-" index="1"/>
Related
Lets assume I have a domain class called Template that looks somewhat like this:
class Template{
String subject
...
}
I save an instance of this class:
Template t=new Template(subject:'Hello ${name}').save()
Now, I fetch this instance inside a method as follows:
def render(Long id){
String name='foo'
Template t= Template.get(id)
println t.subject
}
I want the "println t.subject" to be printed as "Hello foo". What I get is "Hello ${name}".
I want t.subject to dynamically replace the value of variable name - "foo" in place of ${name}.
Can this be achieved in groovy?
I cannot find any documentation of how to do this, or why this cannot be done.
Update:
I tried this on my GroovyConsole.
class Entity{
String name
}
class Template{
String name
String subject
}
String renderTemplate(Template template, Entity entity){
return template.subject
}
Entity e = new Entity(name:'product')
Template template=new Template(name:'emailTemplate',subject:'Product ${e.name}')
renderTemplate(template,e)
The Output I got was:
Result: Product product
class Template {
String subject
// ...
}
Template t = new Template(subject: 'Hello, ${name}').save()
Important: Use single quotes in 'Hello, ${name}' or you will get an error.
def render(Long id) {
String name = "world"
Template t = Template.get(id)
def engine = new groovy.text.GStringTemplateEngine()
def subject = engine
.createTemplate(t.subject)
.make(name: name)
println subject
}
There are a couple of things wrong with the code shown. You have this:
class Template{
String subject
...
}
Then you have this:
Template t=new Template(subject:"Hello ${name}").save()
The Groovy String assigned to the subject property will be evaluated as soon as you assign it to subject because subject is a String. The actual value will depend on the value of the name property that is in scope when that code executes.
Later you have this:
def render(Long id){
String name="foo"
Template t= Template.get(id)
println t.subject
}
It looks like you are wanting that local name property to be substituted into a Groovy String that has been assigned to t.subject, but that isn't how Groovy works. t.subject is not a Groovy String. It is a String.
Separate from that you comment that when you println t.subject that the output is "Hello ${name}". I don't think that is possible, but if that is what you are seeing, then I guess it is.
You can use a transient property to emulate the required behavior:
class Template{
String subject
String getSubjectPretty(){ "Hello $subject" }
static transients = ['subjectPretty']
}
Then you can use:
println Template.get(1).subjectPretty
I've a scenario to pass a List of char values to the query in Grails.
When I pass the List this is what happening
def accounts = ['A', 'B']
AND acct.account_status_cd in '${accounts}
the query looks like "AND acct.account_status_cd in '[A,B]'"
but it should be "AND acct.account_status_cd in ('A','B')"
how to achieve this?
Resolved it by Passing as a String...
String s = keys.collect { "'$it'" }.join( ',' )
It gives me S = 'A','B','C'
A solution could be a NamedQuery inside your domain class, something like this:
class Account {
// code omitted
static namedQueries = {
accountsInList { accountList ->
'in'("account_status_cd", accountList)
}
}
Then you can use this namedQuery like:
Account.accountsInList(['A', 'B']).list()
Ofcourse you can also use a withCriteria.
See the docs for more info:
http://grails.org/doc/2.2.x/ref/Domain%20Classes/createCriteria.html
I have a simple Tag class with only two fields, name and value,
class Tag {
String name
String value
}
and I'm trying to render an XML where I want to search for parts of both parameters via findBy...Ilike().
def getXml = {
render Tag.findAllByNameAndValueIlike("%${params.name}%", "%${params.value}%") as XML
}
But this doesn't give my any results. If I use only one parameter, it works as I expect:
def getXml = {
render Tag.findAllByNameIlike("%${params.name}%") as XML
}
My next question is probably going to be about filtering the results, and adding other "similar" tags to the returns list, so is there a way to solve the above with something like:
def getXml = {
list = Tag.findAllByNameIlike("%${params.name}%")
list.add(Some other stuff)
list.sortBy(Some thing, maby name length)
}
For your multiple-field ilike query you can use withCriteria:
def result = Tag.withCriteria {
ilike('name', "%${params.name}%")
ilike('value', "%${params.value}%")
}
This will return a list of Tag domains whose name matches the provided name and value matches the provided value.
The Criteria DSL will probably let you do most of the filtering you need, but you can also consider using some of the Groovy collection examples here.
You have to put the restrictions(InList, NotNull, etc) on each field of a dynamic finder. If you do not, it assumes equals. Here is what you were looking for:
Tag.findAllByNameIlikeAndValueIlike("%${params.name}%", "%${params.value}%")
Both answer are good. I tried both, but I have to say I like the withcCritia the best. It seems very flexibly.
def result = Tag.withCriteria {
if(params.name != null)
ilike('name', "%${params.name}%")
if(params.value != null)
ilike('value', "%${params.value}%")
}
result.add(new Tag('name': "something"))
render result as XML
I would like to create a helper to return a text one character below the other. Something like that:
S
A
M
P
L
E
The purpose of this helper is to have a table with a heading of only 1 character wide. As you can see on the picture below this is ugly:
Example below looks nice:
I would like something like:
#Html.DisplayVerticalFor(x => x.MyText)
Any idea?
Thanks.
You can create an HTML helper DisplayVertical. (I am not adding the steps of how to create html helpers). The DisplayVertical will first split your text in character array and wrap each character inside a div or any other block level element, which can be inserted desired place.The implementation of DisplayVerticalFor can be something like this :
public static MvcHtmlString DisplayVertical (this HtmlHelper helper, string text)
{
string OutputString = "";
string assembleString = "<div>{0}</div>";
char[] textarr = text.ToCharArray();
foreach( char a in textarr )
{
OutputString += String.Format(assembleString, a);
}
return new MvcHtmlString(OutputString);
}
and in razor it will placed like this :
<div class="style-to-adjust-width-n-height"> #Html.DisplayVertical ("Sample") </div>
If you want to pass on a lambda expression to this html helper like this #Html.DisplayVerticalFor(x => x.MyText) then you need to add lambda expression parsing code to find out the text.
Lastly, this is a very rough code however you can add "TagBuilder" etc to make it more neat and clean.
I am trying to iterate over a list of parameters, in a grails controller. when I have a list, longer than one element, like this:
[D4L2DYJlSw, 8OXQWKDDvX]
the following code works fine:
def recipientId = params.email
recipientId.each { test->
System.print(test + "\n")
}
The output being:
A4L2DYJlSw
8OXQWKDDvX
But, if the list only has one item, the output is not the only item, but each letter in the list. for example, if my params list is :
A4L2DYJlSwD
using the same code as above, the output becomes:
A
4
L
2
D
Y
J
l
S
w
can anyone tell me what's going on and what I am doing wrong?
thanks
jason
I run at the same problem a while ago! My solution for that it was
def gameId = params.gameId
def selectedGameList = gameId.class.isArray() ? Game.getAll(gameId as List) : Game.get(gameId);
because in my case I was getting 1 or more game Ids as parameters!
What you can do is the same:
def recipientId = params.email
if(recipientId.class.isArray()){
// smtg
}else{
// smtg
}
Because what is happening here is, as soon as you call '.each' groovy transform that object in a list! and 'String AS LIST' in groovy means char_array of that string!
My guess would be (from what I've seen with groovy elsewhere) is that it is trying to figure out what the type for recipientId should be since you haven't given it one (and it's thus dynamic).
In your first example, groovy decided what got passed to the .each{} closure was a List<String>. The second example, as there is only one String, groovy decides the type should be String and .each{} knows how to iterate over a String too - it just converts it to a char[].
You could simply make recipientId a List<String> I think in this case.
You can also try like this:
def recipientId = params.email instanceof List ? params.email : [params.email]
recipientId.each { test-> System.print(test + "\n") }
It will handle both the cases ..
Grails provides a built-in way to guarantee that a specific parameter is a list, even when only one was submitted. This is actually the preferred way to get a list of items when the number of items may be 0, 1, or more:
def recipientId = params.list("email")
recipientId.each { test->
System.print(test + "\n")
}
The params object will wrap a single item as a list, or return the list if there is more than one.