0
votes

I'm trying to reduce some repetitive GSP code in my Grails app. The following code works as expected:

<g:textField name="recordValues.0.name" value="${recordValues?.get(0)?.name}"/>
<g:textField name="recordValues.0.age" value="${recordValues?.get(0)?.age}"/>

[edit]recordValues.0.age is actually a Map not a class property, as I originally stated.

However when I try to dynamically set a bunch of these with a list enum, the value attribute is not evaluated:

<g:each in="${fields}" var="prop">
  <g:textField name="recordValues.0.${prop}" value="${recordValues?.get(0)?.prop}"/>
</g:each>

It appears the value attribute is looking for the property Map key called "prop" and is not evaluating it as a variable. I've tried recordValues?.get(0)[prop] with and without ? between but it didn't compile.

Is there some dynamic method I can call with the variable as an argument or an even easier solution?

1
Why do you reference the first item from a list. Is your repetitive GSP code caused by the wrong iteration? I would use <g:each /> to iterate over your recordValues and declare the fields in question as shown in your first example. - stefanglase
Its still in the early phase of development and the "first item from a list" is hard coded in this iteration but we are expecting to have multiple recordValues per page eventually. The actual field names are not coded in the domain object - there is a generic field entity and the GSP is actually setting the name of each field instance. Its not until data is saved that I can iterate over them. So my current refactor is to specify the field names from a enum (not a list as I said in the Q). I didn't write the first version so I'm still trying to grok all the code (and Grails) - nickdos

1 Answers

1
votes

Sorted it myself in the end. Thanks to codespace for making me check the code again and noticing it was a Map I was trying to reference, not an object property. The fact I was using an enum confused the issue as using the regular map.get(var) did not work, I needed map.get(var.name()) instead (maybe I'll encode it as a String field inside the enum to avoid this).

Here's the solution:

<g:each in="${fields}" var="prop">
  <g:textField name="recordValues.0.${prop}" value="${recordValues?.get(0)?.get(prop.name())}"/>
</g:each>