the key for the messages.properties lookup are provided by my Java Class, as you can see here (where i is a variable in a th:each loop):
th:text="#{${i.nameKey}}"
public String getNameKey() {
// getKeyPrefix() generates a unique name from the class attributes
return getKeyPrefix() + ".name";
}
This works fine.
Now I want to check if the value in the messages.properties file is null or empty for the given key:
th:if="${#messages.msg(i.nameKey) != null AND NOT #string.isEmpty(#messages.msg(i.nameKey))}"
But i can't pass the messages object into the isEmpty method.
Any idea?
Thanks!
#messages.msg does not return null if the key is missing. From the docs:
If a message is not found, a default message (like '??msgKey??') is returned.
You should use #messages.msgOrNull instead. As for the second part of the question, there is no reason you can't combine #utility objects. That being said, it looks like you have a typo: the utility object #string does not exist, but #strings does.
th:if="${#messages.msgOrNull(i.nameKey) != null AND NOT #strings.isEmpty(#messages.msgOrNull(i.nameKey))}"
Related
Is there a way to get the string value out of a KeySym value?
For example, out of keyPrintable("a").
If you know the KeySym value is a keyPrintable, you can just get it using the key property. For instance
KeySym kv = ... // something that yields a KeySym
str s = kv.key;
If you don't know it's a keyPrintable you can either check to see if it was built using that constructor, or use pattern matching. So, either
if (kv is keyPrintable) {
// code that uses kv.key to get back the value
}
or
if (keyPrintable(str s) := kv) {
// code that can now use s, which is the key
}
You can also ask if kv has that field, and then use it:
if (kv has key) {
// code that uses kv.key
}
Once you introduce a field name in a constructor, and it has a specific type, you know that same field name has that same type in any additional constructors for the same datatype. So, once we know field key is type str, field key has to be str in any value of type KeySym. That is why it's fine to see if kv has field key and then treat it as a str, nobody could come along later and add a new constructor for KeySym where key has a different type.
We are using Grails 2.4.3 , In our Command
#Validateable
class FreeTextSearchCommand {
String freeText="*"
int pageSize=1
int pageIndex=1
}
And in Controller
def freeTextSearch(FreeTextSearchCommand freeTextSearchCommand){}
So if value comes from Client site is null then I want my default value set , but it does not work
So if value comes from Client site is null then I want my default
value set , but it does not work
If you bind null to a property then the result should be null. That is what the data binder does and it is what the binder is supposed to do. If you want to impose some custom rules you can do that a number of ways. One is by using the BindUsing annotation.
#Validateable
class FreeTextSearchCommand {
#BindUsing({obj, source ->
// bind '*' if there is no corresponding request parameter value...
source['freetext'] ?: '*'
})
String freeText
// etc...
int pageSize=1
int pageIndex=1
}
See http://grails.github.io/grails-doc/2.4.3/guide/theWebLayer.html#dataBinding for more details.
I hope that helps.
question from a groovy newbie:
sql is initiated as follows
final Binding binding = new Binding();
binding.setProperty("sql", sql);
final groovy.sql.Sql sql = Sql.newInstance(dbConfig.getUrl(), dbConfig.getUserName(), dbConfig.getPasswd(),"oracle.jdbc.OracleDriver");
I am running a query in groovy like this
def listOfRows = sql.rows (select column1 from table1);
listOfRows when printed shows contents like [[column1_name:value1], [column1_name:value2], [column1_name:value3]]
I want to check if value2 (a String) exists in the returned list of values from the above query.
I have tried doing listOfRows.contains('value2') and listOfRows.find('value2'),
it complains that the method does not exist for lists..
what's the best way of doing this ?
EDITED: I have corrected the list of printed values. What's being returned is List<GroovyResultSet>
and I have also added the definition of sql.
I would suggest you to take a look at groovy documentation, and particularly to collections documentation (both tutorial and JDK/GDK).
in that case, the most specifically adapted solution would be to use Collection#find() ... with something like
listOfRows.find { it.contains(':value2') }
Which can be translated into human-readable
find the first element in this collection which string contains ":value2".
You probably want
listOfRows.column1.contains( 'value2' )
You are probably invoking this method which takes a GString (note that GString != String) as an argument. According to this question, a string in single quotes is a standard java string, and a string in double quotes is a templatable string.
'hello' //java.lang.String
"hello" //groovy.lang.GString
Try this:
listOfRows.contains("value2")
what i ended up doing is following :
iterate the listOfRows, get all the values for column1 from each GroovyResultSet into a listOfValues ,then check for my values in that list.
def listOfValues=[];
listOfRows.collect(listOfValues){it.getAt('column1')};
if(listOfValues.size()==3){
println('success');
}
I have a nullable DateTime I want to show in ShortDate format if it has a value, but I can't get it right. I am trying to use the null operator ($!{}) here.
It should work like this:
<td>$!{period.Enddate.Value.ToShortDateString()}</td>
But this gives an InvalidOperationException: nullable object must have a value.
Removing the 'Value' part won't work either, that will give the obvious 'System.Nullable has no definition for ToShortDateString' message.
With the conditional operator it works fine, but that one only works for attributes like this:
<td value="$!{period.Enddate.Value.ToShortDateString()}?{period.Enddate.HasValue}"></td>
And I am trying to get it inside the td element, not as an attribute for td.
Am I doing something wrong here, or is this a known issue?
I understand that catching an InvalidOperationException (thrown by the Nullable class) is trickier than catching a NullReferenceException, but I think it is a serious flaw.
Cheers,
Ronald
As of Spark v1.6, here are some options:
use a format specfier -
<td>${ string.Format("{0:M/dd/yy}", period.Enddate) }</td>
or create an additional presentation property -
public string EnddateText
{
get
{
var result = Enddate.HasValue ? Enddate.Value.ToShortDateString() : string.Empty;
return result;
}
}
<td>${ period.EnddateText }</td>
Is it possible to include i18n property values within other internationalized messages in grails?
I have a domain class containing 2 properties, "minDelay" and "maxDelay", and I want to write an internationalized message referencing the labels to both.
I wrote a custom validator (maxDelay must be bigger than or equal to minDelay):
maxDelay(validator:{
value, reference ->
if (value < reference.minDelay) {
return ['custom.error', it]
} else {
return true;
}
})
when it fails, I'm printing the property stub.maxDelay.custom.error.
In my messages.properties there are the properties:
stub.maxDelay.custom.error=Property [{0}] must be bigger than value of minDelay
stub.minDelay.label=Min. delay (ms)
stub.maxDelay.label=Max. delay (ms)
How can I use the value of the stub.minDelay.label property instead of static text?
The error message should read like:
"Property [Max. delay (ms)] must be bigger than value of [Min. delay (ms)]"
I've tried referencing it like {stub.minDelay.label} or ${stub.minDelay.label} but all I get is a parse error from grails.
Perhaps I'm approaching this in the wrong way, would it be possible to inject the label via a numeric parameter in the validator? Like for example if the error message were:
stub.maxDelay.custom.error=Property [{0}] must be bigger than value of [{1}]
Note that there is also third parameter, of class org.springframework.validation.Errors, that can be used for fine-tuning your error messages, like:
maxDelay(validator:{ value, reference, errors ->
if (value < reference.minDelay) {
errors.rejectValue('maxDelay', 'stub.maxDelay.custom.error', [value, obj.minDelay], 'oops')
}
})
it will work for message:
stub.maxDelay.custom.error=Property [{0}] must be bigger than value of [{1}]