grails i18n label cross-referencing? - grails

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}]

Related

Thymeleaf: Check if message with dynamic key is null or empty

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))}"

Dart Generic Function with Subtype function call

I am not sure if this is even possible but here's my setup:
I have basically 2 Maps holding a special identifier to get some objects.
these identifier is like a versioning number, i may have data in version 8 that belongs to meta version 5. But at the same time, Meta versions up to 10 may exist and not every meta version holds information about every data, so here's where the _filter kicks in.
The filter is able to find to any given value the correct object. So far so good.
My question belongs to the following: (last codeline)
how am i able to say "if you have no matching candidate, generate me a default value"
For this purpose, i tried to force a named constructor with a super class for "Data" and "Meta" called "BasicInformation".
But even if i implement this, how do i call something like T.namedConstructor(); ?
class Repo{
Map<int, Data> mapData;
Map<int, Meta> mapMeta;
Data getData(int value)
{
return _filter<Data>(mapData, value);
}
Meta getMeta(int value)
{
return _filter<Data>(mapMeta, value);
}
T _filter<T extends BasicInformation>(Map<int, T>, int value)
{
//fancy filtering technique
//....
//speudo code
if (found) return map[found]; //speudo code
else return T.generateDefault();
}
}
I've found the following stackoverflow entry: Calling method on generic type Dart
which says, this is not possible without adding a function call.

How to simulate undefined in Dart

In JS, there is undefined and null. Undefined means "no value", null means "value equivalent to emptiness".
In Dart however (and possibly in other languages, I don't know, but right now I'm using Dart), there is no undefined, only null. Therefore it is impossible to make the distinction between a value equivalent to emptiness and the absence of value.
Is there a standard way of simulating this difference in Dart?
No. The null value (of type Null) is the only built-in value that represents the absence of a value. It does not distinguish on why the value is absent.
It's also (almost) the only type you can combine with another type directly in the type system. With null safety, you'll be able to write int? for int-or-Null.
If you want another marker for absence, you can use (or write) an Option type like:
abstract class Option<T> {
final T value;
bool get hasValue => true;
Option(this.value);
factory Option.none() => const _OptionNone();
}
class _OptionNone implements Option<Never> {
const _OptionNone();
bool get hasValue => false;
T get value => throw UnsupportedError("None option has no value");
}
Then you can represent either value or no value.
(There are existing implementations of such a class, for example in the quiver package).

How to set default value if Command value is null

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.

Spark null operator not working with nullable types

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>

Resources