IndexOutOfBoundsException when binding children - grails

I have the following gsp in Grails 2.1.1 (simplified version):
<g:form ...>
<g:each in="${team.players}" var="player" status="i">
<g:hiddenField name="players[${i}].id" value="${player.id}" />
<g:textField name="players[${i}].name" value="${player.name}" />
<g:textField name="players[${i}].position" value="${player.position}" />
</g:each>
</g:form>
Given that the particular Team has 2 players, when I do the following in the controller I get java.lang.IndexOutOfBoundsException: Index: 1, Size: 1:
def teamInstance = Team.get(params.id)
teamInstance.properties = params // this is where IndexOutOfBoundsException happens
teamInstance.save()
Interestingly, when I remove players[${i}].id parameter the error goes away, but then the data for the two players is randomly swapped around because Grails doesn't know how to match the a player from the form to one in the players collection.
Anyone know what is going on here?
EDIT: Here is a sample app: https://github.com/zoran119/binding-test

Related

Passing values to input through g:each iteration

Say if i have this data from my controller that i want to pass it to my GSP
def test = [value: ['TEST1', 'TEST2', 'TEST3']]
And in my GSP, i have the following
<g:set var="counter" value="${0}"/>
<g:set var="count" value="${count}"/>
<g:while test="${counter < count}">
<g:set var="counter" value="${counter+1}"/>
<g:each var='obj' in='${test}' status='i'>
<g:textField id='justATest1' name='justATest' value='obj.value'>
<g:textField id='justATest2' name='justATest' value='obj.value'>
<g:textField id='justATest3' name='justATest' value='obj.value'>
</g:each>
</g:while>
And i want it so that justATest1 will get TEST1, justATest2 will get TEST2 and justATest3 will get TEST3.
How can i achieve that?
Assuming your model contains the following
def myAction() {
[value: ['TEST1', 'TEST2', 'TEST3']]
}
This should do it
<g:each status="i" in="${value}" var="item">
<g:textField id="justATest${i}" name='justATest' value="${item}">
</g:each>
Ok seems i managed to iterate object in GSP
<g:each var='obj' in='${test}'>
<g:each var='subObj' in='${obj.value}'>
<p>${subObj}</p>
</g:each>
</g:each>
But kind of not elegant enough.
I can do it too with this, as what Donal put in his answer
<g:each var='obj' in='${test.value}'>
<p>${obj}</p>
</g:each>
But it would be hard i think if i want to iterate each item inside test object separately and uniquely.
Anyone please feel free to fix my approach.

displaying bean class items on view - beginner

The bean class looks like this:
String houseNo
String address
Person person
The view looks like this
<g:form action="save">
<fieldset class="form">
<g:render template="form" />
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save"
value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
According to my knowledge in Grails, i think is <g:render template="form" /> will pull all form attributes and display it.
But what i want to do is Instead of displaying a drop-down for Person, i want to display all Person related fields like personName, personAge. How can i display these fields in a label underneath ?
Help
You're correct about the way g:render works, the template part refers to a GSP which will look through the bean values and print them according to the html + groovy markup in "_form.gsp" (located in your views folder under the controller name).
To change the way the Person domain object is displayed, simply edit this "_form.gsp" and take out the 'select' html code - replacing it with groovy markup using the property values of the bean, eg.
${beanName.person.personName} //(use the existing code to help workout the bean name etc)
Hopefully that helps you on your way.

Grails populate g:select from database

I ran into an issue while populating domain object values on a gsp page by using a g:select tag.
<g:select name="demo" id="demo"
value="${dm.id}"
noSelection="${['null':'Select..']}"
from="${dm}"
optionValue="${dm.type}"/>
In my controller, I have an object which gathers values from my domain. I tried writing this object in the controller both as:
def d = Demo.getAll()
and def d = Demo.list()
Both of these returned an exception while trying to use the g:select tag. The error was:
No signature of method: Demo.getAt() is applicable for argument types: (java.util.ArrayList) values: [[One, Two, Three, Four, Five]]
I was able to get my code working by simply removing the g:select tag and writing the following in my gsp:
<select name="demo" id="dm">
<option value="">Select!</option>
<g:each in="${dm}" status="i" var="dm">
<option value="${dm.id}">${dm.name}</option>
</g:each>
</select>
However, I would like to know how to make this work with the g:select tag, for my future reference.
Thanks in advance!
I see two issues in your select:
<g:select name="demo" id="demo"
value="${dm.id}"
noSelection="${['null':'Select..']}"
from="${dm}"
optionValue="${dm.type}"/>
value shouldn't be looking at the collection for the id. I believe this is why you are getting your error. value should be whatever instance's id you've passed into your view.
optionValue doesn't required an expression.
Controller action
def someAction() {
def dm = Demo.get(params.id)
def demos = Demo.list()
[dm: dm, demos: demos]
}
view
<g:select name="demo" id="demo"
value="${dm.id}"
noSelection="${['null':'Select..']}"
from="${demos}"
optionValue="type"/>

Updating many instances in one view

I'm starting with Grails and I don't know how should I face the following use case.
The app is about sports results prediction, so I have in my domain "Match" and "Prediction", and I want to have one view where the user can update all the predictions of matches that haven't been played yet.
So far I've defined a method in my "PredictionController" that searches all the already existing predictions of games that have to be played and generates new Prediction instances for any new Match with a date higher than now. I've created a view for that method and I'm getting correctly all the predictions that I should complete or update, and I've defined in my controller another method for the form sumbission (so I'm trying to resolve this in the same way that the 'create' and 'update' scaffolded methods work).
My question is, How can I access to all the Predictions modified by my view? How can I send all the predictions to my update method? Is it defining a hidden field with a variable containing all the collection?
This is the form in my GSP view:
<g:form action="savePredicctions">
<fieldset>
<g:each in="${predictions}">
<li>
<div>
${it.match.homeTeam}
<g:field name="${it.match}.homeGoals" type="number" value="${it.homeGoals}" />
</div>
-
<div>
<g:field name="${it.match}.awayGoals" type="number" value="${it.awayGoals}" />
${it.match.awayTeam}
</div>
</li>
</g:each>
</fieldset>
<fieldset class="submit">
<g:submitButton />
</fieldset>
</g:form>
You can use a command object to store the instances of Prediction.
#Validateable
class PredictionCommand {
//data binding needs a non-null attribute, so we use ListUtils.lazyList
List<Prediction> predictions = ListUtils.lazyList([], FactoryUtils.instantiateFactory(Prediction))
}
In your view, you need to control the index of your list, and send the attributes of Prediction to the controller:
<g:each in="${predictions}" status="i">
<g:textField name="predictions[$i].homeGoals" />
<g:textField name="predictions[$i].awayGoals" />
</g:each>
And in your controller you can use bindData() to bind params to your command:
class CommandController {
def save() {
PredictionCommand command = new PredictionCommand()
bindData(command, params)
println command.predictions
}
}

Unclosed GSP expression: Grails GSP engine does not resolve nested GSP expression

I need to create a custom gsp whose domain model is designed as follows
class Question {
SortedSet<Choice> choiceCollection;
static hasMany = [choiceCollection:Choice]
static mappping = {
choiceCollection(joinTable:false)
}
}
Each Question object has five Choices. So, i create the following snippet of code
create.gsp
<g:each var="i" in="${(1..5)}">
<div class="fieldcontain required">
<label for="description">
Option ${i}.
<span class="required-indicator">*</span>
</label>
<g:textArea name="choiceCollection[${i}].description" cols="40" rows="5" maxlength="2000" value="${questionInstance?.choiceCollection[${i}]?.description}"/>
</div>
</g:each>
Although Grails GSP engine complains Unclosed GSP expression which is not true - g:textArea is closed as you can see above -, i believe the real problem is the expression
${questionInstance?.choiceCollection[${i}]?.description}
which involves nested GSP expressions.
Question: am i missing some feature ? If so, what should i do to overcome my obstacle ?
Grails version: 2.1.1
Shouldn't
${questionInstance?.choiceCollection[${i}]?.description}
be
${questionInstance?.choiceCollection[ i ]?.description}
The set bit:
Try something like:
<g:each var="choice" status="i" in="${questionInstance?.choiceCollection}">
So i still contains your index, but choice contains what you were trying to get with questionInstance?.choiceCollection[${i}]

Resources