translate a HTML select element in Grails - grails

thought this would be easier.... imagine a <g:select /> like this:
<g:select name="type.id" from="${Type.list()}"
value="${domainInstance?.type?.id}" />
with two domain classes like this (please forgive me if these artificial classes are not error free)
class Domain {
Type type
}
class Type {
String name
}
I would now like to translate the entries of the select element. The following code first looked good:
<g:select name="type.id" from="${Type.list()}"
valueMessagePrefix="type.name"
value="${domainInstance?.type?.id}" />
with entries in the messagebundle like this:
type.name.type1 = red
type.name.type2 = green
Problem: not only the text was translated, but the option keys, too!
So I tried to add a optionKey='id':
<g:select name="type.id" from="${Type.list()}"
valueMessagePrefix="type.name"
value="${domainInstance?.type?.id}"
optionKey='id' />
This switched the keys to the id - great, but the text switched to the id, too :-(
Any idea how to solve this?

thanx to grails beeing open source, I just checked the code: http://grails.org/doc/latest/ref/Tags/select.html#select
It seems that valueMessagePrefix is ignored as soon as you use optionKey or optionValue. But optionValue can take a closure:
<g:select name="type.id" from="${Type.list()}"
value="${domainInstance?.type?.id}"
optionKey="id"
optionValue="${ {name->g.message(code:'type.name'+name) } }"/>
at least, this works.

Can't you just add an optionValue?
<g:select name="type.id" from="${Type.list()}"
valueMessagePrefix="type.name"
value="${domainInstance?.type?.id}"
optionKey='id'
optionValue='name'/>
Sorry I haven't had a chance to test this exact code, but have done similar things like this with no problems.

Related

Build-in Grails tags do not work

During grails application upgrade from 1.3.8 to 2.3.9 I run into the problem that grails build-in tags are ignored.
For example lets say that GSP page has two tags:
<g:if test="${true}">OK</g:if>
<g:hiddenField name="test" />
then the result of execution will be:
OK
<g:hiddenField name="test" />
but expected result is :
OK
<input type="hidden" name="test" />
Basically tags from grails-web-2.3.9.jar are working fine but from grails-plugin-gsp-2.3.9.jar are completely ignored.
Any clue why this happens is appreciated. Thank you.
UPDATE:
I found that while executing TagLibraryLookup.afterPropertiesSet() method grailsApplication object is null, so the tag lib is not registered. Now it is not clear why it is null...
Solotion:
The problem was that within static constraints = { } of domain object it was a call of
ApplicationHolder?.getApplication().getMainContext()?.getBean(serviceName) method. It prevented the application from initialization of all required spring/grails beans by changing initialization sequence/flow.
You're missing some double-quotes here:
<g:if test=${true}>OK</g:if>
<g:hiddenField name="test" />
If you add them:
<g:if test="${true}">OK</g:if>
<g:hiddenField name="test" />
Does that help? Also, check for any changes to the default encoding that was made in Config.groovy after you upgraded.

struts 2: equal symbol expected error

I am trying to set the text in a button to either 'Enable' or 'Submit' depending on the value of a action class member(mode). But it is reporting an error which is saying 'equal symbol expected' on the first line. I searched and found that there are questions regarding 'equal symbol expected' error but nothing specific to Struts 2 tags. Neither I could spot any obvious error as missing closing quotes.
It would be nice if anyone can help.
<s:set name="submitButtonLabel" value="<s:if test="mode.equals('enable')">Enable</s:if> <s:else>Submit</s:else>" />
<s:submit value = "%{#submitButtonLabel}" cssClass="btn btn-gray" />
Try this:
<s:submit value="%{mode.equals('enable') ? 'Enable' : 'Submit'}" />
You cannot nest tags like that. Write your <s:if> inside <s:set> tag instead.
<s:set name="submitButtonLabel">
<s:if test="mode.equals('enable')">Enable</s:if>
<s:else>Submit</s:else>
</s:set>

Grails <g:if> in <g:select>

I have this <g:select> in a .gsp file. But unlike any ordinary <g:select>'s this one would have the attribute disabled="" if a certain condition is met.
Following the code:
<g:select name="test"
from="${["foo1","foo2"]}"
<g:if test="${true}">disabled=""</g:if> />
It returned an error: Grails tag [g:select] was not closed
But when I change it into this:
<g:select name="test"
from="${["mu1","mu2","mu3"]}"
${ if(true) { println "disabled=\"\"" } }/>
It returned this error: Attribute value must be quoted.
Both of the error message are under the exception, org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException
The question is how could we make this work? Is there a possible answer without using a custom TagLib?
The GSP form field tags treat disabled as a boolean property, so you can say
<g:select .... disabled="${true}" />
Generally you should be able to use any expression under the usual Groovy-truth rules but I believe it makes a special case for the strings "true" and "false" (the latter would normally be considered true under Groovy-truth rules as a non-empty string). If in doubt you can always say
disabled="${(someExpression) as boolean}"
No need to use the println, try this
<g:select .... ${(conditional)?"disabled":""} ... />
<g:select disabled="${true}"...
is fine but when you submit and it is a required field the value will not be submitted so use this jQuery code to enable the field when pressing the submit button
$(function() {
$('form').on('submit', function() {
$(this).find(':disabled').removeAttr('disabled');
});
});

Get id of parent naming container in template for in render / update attribute

I have a template and in its Definition I use several forms and buttons.
The problem is the definition (define) xhtml file does not know the component hierarchy.
And for example I want to update the element "table2" in a different form in the same define file.
Template Insert:
<p:tabView id="nav"> <!-- nav -->
<ui:insert name="content_nav">content navigation</ui:insert>
</p:tabView>
defines the first level of my hierarchy "nav"
Template define:
<ui:define name="content_nav">
<h:form id="form1"> <!-- nav:form1 -->
<h:dataTable id="table1"/> <!-- nav:form1:table1 -->
<p:inputText value="#{bean.value}"/>
<p:commandButton action="..." update="nav:form2:table2"/>
</h:form>
<h:form id="form2">
<h:dataTable id="table2"/> <!-- nav:form2:table2 -->
<!-- other elements -->
</h:form>
</ui:define>
In my define part I don't want to know "nav"!
How can I do this? or how can I move one naming component upwards?, or save the highest parent complete id in a variable?
sometimes i saw something like:
update=":table2"
But I could not find any informations about this?, the JavaEE 6 documentation just mentions the # keywords.
Ugly, but this should work out for you:
<p:commandButton action="..." update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2" />
As you're already using PrimeFaces, an alternative is to use #{p:component(componentId)}, this helper function scans the entire view root for a component with the given ID and then returns its client ID:
<p:commandButton action="..." update=":#{p:component('table2')}" />
ugly answer works well
update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2
mainly more useful updating from opened dialog to parent datatable
You may use binding attribute to declare EL variable bound to JSF component. Then you may access absolute client id of this component by using javax.faces.component.UIComponent.getClientId(). See example below:
<t:selectOneRadio
id="yourId"
layout="spread"
value="#{yourBean.value}"
binding="#{yourIdComponent}">
<f:selectItems value="#{someBean.values}" />
</t:selectOneRadio>
<h:outputText>
<t:radio for=":#{yourIdComponent.clientId}" index="0" />
</h:outputText>
Try this:
<h:commandButton value="Click me">
<f:ajax event="click" render="table" />
</h:commandButton>
Additionally to the solutions above I had the problem, that I had to dynamically generate the to-be-updated components (many) based on server-side logic (with maybe harder to find out nesting).
So the solution on the server-side is an equivalent to update=":#{p:component('table2')}"1 which uses org.primefaces.util.ComponentUtils.findComponentClientId( String designId ):
// UiPnlSubId is an enum containing all the ids used within the webapp xhtml.
// It could easily be substituted by a string list or similar.
public static String getCompListSpaced( List< UiPnlSubId > compIds ) {
if ( compIds == null || compIds.isEmpty() )
return "" ;
StringBuffer sb = new StringBuffer( ":" ) ;
for ( UiPnlSubId cid : compIds )
sb.append( ComponentUtils.findComponentClientId( cid.name() ) ).append( " " ) ;
return sb.deleteCharAt( sb.length() - 1 ).toString() ; // delete suffixed space
}
called via some other method using it, e.g. like ... update="#{foo.getCompListComputed( 'triggeringCompId' )}".
1: first I tried without too much thinking to return public static String getCompListSpaced0() { return ":#{p:component('table2')}" ; } in an ... update="#{foo.getCompListSpaced0()} expression, which of course (after thinking about how the framework works :) ) is not resolved (returned as is) and may cause the issues with it some users experienced. Also my Eclipse / JBoss Tools environment suggested to write :#{p.component('table2')} ("." instead of ":") which did not help - of course.

Grails GSP <g:set> tag set as integer?

Using Grails' GSP <g:set> tag, is it possible to specify the type of the variable? I want to declare an integer variable, but <g:set> always declares a sting. For example:
<g:set var="x" value="100"/>
${x.getClass()}
${x+23}
results in
class java.lang.String
10023
I'd like to declare x as an integer. I noticed that using the JSP tag <% int x=100; %> results in:
class java.lang.Integer
123
Is there a way to do this the Grails/GSP way?
Use the ${} syntax when defining the value. For example:
<g:set var="x" value="${100}"/>
You can see the tag doc for g:set for more info.
Just as an additional comment for someone who comes across this since it is the only useful result on the Internet for and casting/Int/Sring/etc. This example works in the case of variables:
<g:set var="printLeft" value="${offer?.metaInfo?.redeemPrintY as Integer}"/>
<g:set var="printTop" value="${offer?.metaInfo?.redeemPrintX as Integer}"/>
<g:set var="printWidth" value="${offer?.metaInfo?.redeemPrintW as Integer}"/>
<g:set var="printHeight" value="${offer?.metaInfo?.redeemPrintH as Integer}"/>
...
<area shape="rect" coords="${printLeft},${printTop},${printLeft+printWidth},${printTop+printHeight}" onClick="printOffer();" />

Resources