Access individual elements in a list - grails

I have a list of, let's say, persons. Every person has a field that is "friend", that could be "yes" or "no". Their "friendship" status is presented in a column in the list:
<g:if test="${person.friend.status=='no' }">
<td><g:textField name="status" value="${person.friend.status}" readonly="readonly" style="width:60px;border:0px; background:transparent;color:black"/></td>
<td style="width:20px">
<g:actionSubmitImage action="acceptFriend" value="aceptar" src="${resource(dir: 'images', file: '/skin/tick_16.png')}" style="width:5px;height:8px;"/>
</td>
<td>
<g:actionSubmitImage action="refuseFriend" value="aceptar" src="${resource(dir: 'images', file: '/skin/wrong_16.png')}" style="width:5px;height:8px;"/>
</td>
</g:if>
As you can see, when the friend status is "no", two buttons are presented, one to say "that person is my friend" and another one to say "this person is not my friend". My question is:
When i click on the image that says "this person is my friend", I call the action "acceptFriend". But, how to access to the indivivual person instance, to change his status to "yes", and persist in the database? I think it may be with the "params" variable, but how to store it in the params to be accessed in the Controller?
Thank you!

I believe, you cannot use the g:actionSubmitImage like this, because in the tag's documentation is written:
You cannot use multiple actionSubmitImage tags within the same form and have it work in Internet Explorer 6 or 7 unless you add some custom JavaScript. See this page for a bit more information and a workaround.
The correct solution would be to have a form per friend in list and then you can easily pass the ID of the domain class.

The actionSubmitImage creates a submit button in some form.
Create the form for each person in the list you're iterating.
In that form, add a hidden field named "id" with a value="${person.id}", and in acceptFriend action read it from params.id.

<img src="${resource(dir: 'images', file: '/skin/wrong_16.png')}" style="width:5px;height:8px;" />
This is not tested code, just to give you the idea.

By request of Tom Metz, i post the snippet with both g:actionSubmitImage tags working:
<form>
<g:hiddenField name="contrato" value="${factura.id}"/>
<td> <g:link title="${message(code :'contratosVer.tooltip')}" controller="campaign" action="show" id="${factura.id}" style="width:160px"> <g:img dir="images" file="/skin/eye_16.png"/></g:link> </td>
<td><g:textField name="campaign" value="${factura.nombre}" readonly="readonly" style="width:120px;border:0px; background:transparent;color:black"/></td>
<td><g:textField name="total" value="${factura.presupuestosPendientes.total}" readonly="readonly" style="width:40px;border:0px; background:transparent;color:black"/></td>
<g:if test="${factura.estado=='Espera'}">
<td><g:textField name="estado" value="${factura.estado}" readonly="readonly" style="width:60px;border:0px; background:transparent;color:black"/></td>
<td style="width:20px">
<g:actionSubmitImage action="aceptarCamp" value="aceptar" src="${resource(dir: 'images', file: '/skin/tick_16.png')}" style="width:5px;height:8px;"/>
</td>
<td>
<g:actionSubmitImage action="rechazarCamp" value="aceptar" src="${resource(dir: 'images', file: '/skin/wrong_16.png')}" style="width:5px;height:8px;"/>
</td>
</g:if>
<g:else>
<td><g:textField name="estado" value="${factura.estado}" readonly="readonly" style="width:65px;border:0px; background:transparent;color:black"/></td>
<td></td><td></td>
</g:else>
<g:set var="desc" value="${result.toString()}" />
<g:if test="${desc.size() > 120}"><g:set var="desc" value="${desc[0..120] + '...'}" /></g:if>
</form>
Sorry for the delay, mate, but I was away from work for three days.

Related

Grails - Edit - does not retain the values when created

Grails issue :
When clicking over the Edit in the following screen : Domain and Variable values does not seem to retain their values (When creating it, we are able to enter the values - Domain and Variable, but it does not retain the values when editing..
Clicking over EDIT in the following screen :
does not retain the values of domain and variable alone:
.gsp code below
<tr>
<td>Domain<span style="color: red">*</span></td>
<td><g:if test="${isCreate}">
<g:select class="statSele" id="domain_name" name="domain_name" from="${com.datumrite.master.DomainMaster.list()}" optionKey="id" noSelection="['':'Select Domain']" onchange="${remoteFunction(
action:'driveVariableFromDomain',
params:'\'id=\'+escape(this.value)',
update: 'variable_select'
)}"></g:select> <br>
</g:if>
<g:else>
<input disabled="true" id="dN" name="name" type="text" style="margin-bottom:4px" value="${(data.domain_name instanceof String)?'':com.datumrite.master.DomainMaster.get(data.domain_name)}" />
</g:else>
</td>
</tr>
<tr>
<td>Variable<span style="color: red">*</span></td>
<td><g:if test="${isCreate}">
<span id="variable_select">
<g:select class="statSele" name="var_name" from="${[]}" value="${data?.var_name}" noSelection="['':'Select Variable']"></g:select></span> <br>
</g:if>
<g:else>
<input disabled="true" type="text" name="name" style="margin-bottom:4px;margin-left:5px" value="${data?.var_name}" />
</g:else></td>
</tr>
<tr>
<tr>
<td>Condition<span style="color: red">*</span></td>
<td><g:if test="${isCreate}">
<g:select class="statSele" id="constrain_type" name="constrain_type"
from="${['Lesser than','Greater than','Lesser than nor Equal','Greater than nor Equal','Equal To','Not Equal To']}"
value="${data?.constrain_type}" noSelection="['':'Select Condition']">
</g:select>
</g:if>
<g:else>
<input disabled="true" name="name" value="${data?.constrain_type}" type="text" style="margin-bottom:4px"/>
</g:else></td>
</tr>
And, I am using MySQL DB for the same.
can anyone help me with this issue ?
You need to make sure the subscription instance is passed when you click Edit link. (possibly under <g:link...> tag) The gsp you've posted is for create view. Check your List of Subscription view. (possibly show.gsp)

g:each iterator value not being applied in name of input

So I've got a basic, g:each like so: -
<g:each in="${results}" status = "i" var="item">
<tr id = ${i} class="${(i % 2) == 0 ? 'even' : 'odd'}" name="main">
<td colspan="3">
<table id = "sub">
<tr>
<td><b>Action</b></td><td>
<g:select style="width:375px;"name="events[$i].id" from="${framework.EventType.list(sort:"userEventType")}" required="required" optionKey="id" value="${item.event_id}" /></td>
<td><b>Object</b></td>
<td>
<input type="text" name="any[$i].id">
<g:select style="width:550px;"id="objectID[$i]" name="objectID[$i].id" from="${framework.Object.list(sort:"objDesc")}" optionKey="id" required="" value="${item.object_id}" class="many-to-one"/>
<richui:autoComplete name="autocomp[$i].id" value= "${item.object_description}" action="${createLinkTo('dir': 'object/searchAJAX')}" maxResultsDisplayed="20" minQueryLength ="3" onItemSelect="youPickedThis(id,'autocomp[$i].id')" />
</td>
</tr>
</table>
</td>
</tr>
</g:each>
Absolutely everything within here is generated in the html with the correct names (i.e. [$i] becomes [0] on the first each, [1] on the second and so on. But the very first input (type text) just names them all "any[$i].id"!
Anyone have the remotest idea why the first input is too good to pick up up whereas the other elements just get on with it as they should?
The only difference I can see is that the <input type="text"> is a plain HTML tag whereas all the other places where you're using $i are attributes of GSP tags (richui:autocomplete and g:select). Try using ${i} instead:
<input type="text" name="any[${i}].id">
I wasn't aware that the short form (without using braces) was valid anywhere in a GSP, but the longer brace form will definitely work in all cases.

Struts 2 select tag - Using the tag (with the same list) multiple times on a page does not work

I need to be able to use the same drop down list multiple times on a page. The first time i use the 'list' on the select tag, it works fine. The same list does not populate the second select tag i use it on. Here are the details.
In the action class, i populate the ArrayList containing values i need to populate the select tag.
setNames(new SomeDAO().getNames());
In the JSP
<s:select list="names"
id="nameList"
listKey="nameId"
listValue="userName"
/>
This select list populates just fine. If I use the following select tag on the same page (using the same list), it fails to print.
<s:select list="names"
id="rName"
listKey="nameId"
listValue="userName" />
If i replace the 'list' above with #{'test':'test'} (hardcoded list), the tag shows up fine. Looks like the property i set in the Action is getting cleared after the first use. Is that whats happening or am i doing something wrong? I get an 'IllegalStateException: Response already committed' error
Edit 1:
setNames() is used in the action method that deals with the JSP page. It is a simple getter function.
In the JSP, here is what i have.
<tr>
<td align="left" class="td-plain">Add New:</td>
<td class="td-plain">
<s:select list="names"
id="addNameID"
name="addUserNameID"
listKey="reinsId"
listValue="reinsName"
headerKey=""
headerValue="--User Name--"
/>
</td>
<td class="td-plain"><input id="addTreatyNumber" type="text" /></td>
<td class="td-plain"><input id="addReinsPercentage" type="text" /></td>
<td class="td-plain"><input id="addFlatDollarRetentionAmt" type="text" /></td>
<td class="td-plain">
<%if(finance){ %>
<input type="button" class="greyButton" value="Add" onclick="addReinsInfo()"/>
<%}else{ %>
None
<%} %>
</td>
</tr>
and then later down on that page, i have
<tr id='<s:property value="caseGroupId"/>:<s:property value="treatyId"/>'>
<td class="td-plain"><input type='checkbox' id='<s:property value="caseGroupId"/>:<s:property value="treatyId"/>'/></td>
<td class="td-plain">
<s:select list="names"
id="rName"
name="dName"
listKey="reinsId"
listValue="reinsName"
headerKey=""
headerValue="--User Name--"
/>
</td>
<td class="td-plain_"><s:textfield id="tNumber" value="%{treatyNumber}"/></td>
<td class="td-plain_"><s:textfield id="tPercentage" value="%{reinspercentage}"/></td>
<td class="td-plain_"><s:textfield id="rAmount" value="%{flatDollarRetentionAmt}"/></td>
<td class="td-plain"><input type="button" value="Delete" class="greyButton"/></td>
</tr>
If I change the 'list' in the second tag to
list="#{'Test':'Test'}"
the tag shows up fine. Please let me know if i can provide any further info.
Edit 2: I was able to get this to work by setting the drop down list values to the session.
As asked by #Dave and #Quaternion, post the relevant Java/JSP code.
But until then... I've noted that you are not using name attribute in Struts Selects;
while you can refer multiple times from different tags to the same source (the list attribute), to populate the Select from the same list of objects, you should instead specify a different name for each one, to define which variable (sent back to the Action) contains the selected value of which Select;
this may not be the answer to the current question but it will show up to you soon.

How to implement this validation in a Knockout-based form?

I started to work on an ASP.NET MVC4 solution with the SPA template (Single Page Application).
The starting template manage some todo lists with a kind of post-it design.
I slightly modified the template this way:
no more post-it design for dislaying elements
but a table to list all elements + delete + edit button on each element
at the end of the table: an add button
I have now the ability to edit one element in a form tag like this:
<form data-bind="with: currentTodoList, validate: true">
<h1>Edition</h1>
<table>
<tr>
<td>ID</td>
<td><b data-bind="text: todoListId"></b></td>
</tr>
<tr>
<td>User ID:</td>
<td><input class="required" data-bind="value: userId" /></td>
</tr>
<tr>
<td>Title:</td>
<td><input class="required" data-bind="value: title" /></td>
</tr>
<tr>
<td>Category:</td>
<td><input data-bind="value: category" /></td>
</tr>
</table>
<p>
<button data-bind="click: $parent.saveTodoList">Save</button>
<button data-bind="visible: todoListId, click: $parent.deleteTodoList">Delete</button>
<button data-bind="click: $parent.showGrid">Cancel</button>
</p>
</form>
As you can see above, I set the validate data-binding on the form tag and I have some input element with the class required.
When I test this implementation it doesn't work as expected. Example:
If I clear (empty) the userId field (which is required) I have a red validation message (picture 1). OK.
If I fill this userId field again, the red validation messaged disappeared. OK.
Then if I clear (empty) the title field (which is also required) I have the red validation message next to the userId field (picture 2). NOK.
The inverse is also true: userId <--> title. Any idea where is the problem?
Here is a link to download my test VS2012 solution to reproduce the problem.
Ok, so I played with your markup a little, with slight modification to the view model (not using a list, but editing a single entry).
Take a look at this jsfiddle - http://jsfiddle.net/Zxjrb/1/
I have added a span for validation message for ID and User ID, skipped the span for Title and Category.
<span data-bind='visible: todoListId.hasError, text: todoListId.validationMessage'> </span>
You can see the messages coming up, when Id or UserId field being empty, and that not happening for the title/category fields.

Grails dynamic scaffold with hasMany: is it a bug or am I misconfiguring?

I'm a Grails noob and running into something that seems to be a bug, but it is entirely possible I'm not configuring everything correctly.
I've got two simple Domain Classes:
class Player {
String firstName
String lastName
static constraints = {
firstName(blank:false)
lastName(blank:false)
}
String toString() { lastName + ", " + firstName }
}
and
class Team {
String mascot;
static hasMany = [players:Player]
static constraints = {
mascot(blank:false)
}
}
I have controllers for both that do nothing beyond dynamic scaffold these two Domain Classes.
But even when I have a list of Players in my DB, I don't get a multi-select box for them when creating a new Team.
However, the multi-select shows up when I go to edit a Team
Is this a bug in the dynamic scaffolding for new items, do I misunderstand how this is supposed to work, or is there something else I need to declare here?
Any help is hugely appreciated! I've got screenshots that StackOverflow won't let me add because of my newness, but I'd be happy to show them another way if that'll help.
I finally figured this out and wanted to pass on what I did just in case someone else runs into it.
When I generated the views for Team, the form block in edit.gsp looks like this:
<input type="hidden" name="id" value="${teamInstance?.id}" />
<input type="hidden" name="version" value="${teamInstance?.version}" />
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="mascot">Mascot:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:teamInstance,field:'mascot','errors')}">
<input type="text" id="mascot" name="mascot" value="${fieldValue(bean:teamInstance,field:'mascot')}"/>
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="players">Players:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:teamInstance,field:'players','errors')}">
<g:select name="players"
from="${Player.list()}"
size="5" multiple="yes" optionKey="id"
value="${teamInstance?.players}" />
</td>
</tr>
</tbody>
</table>
</div>
<div class="buttons">
<span class="button"><g:actionSubmit class="save" value="Update" /></span>
<span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
</div>
</g:form>
but the form block in create.gsp looks like this:
<g:form action="save" method="post" >
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="mascot">Mascot:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:teamInstance,field:'mascot','errors')}">
<input type="text" id="mascot" name="mascot" value="${fieldValue(bean:teamInstance,field:'mascot')}"/>
</td>
</tr>
</tbody>
</table>
</div>
<div class="buttons">
<span class="button"><input class="save" type="submit" value="Create" /></span>
</div>
</g:form>
In other words, for this corner case, the default Create view omits the widget to properly display the multi-select list. When I did a copy and paste of the missing code, the dynamically scaffolded controller picked it up and persisted it as expected. So, it's definitely a bug in the view generation code.
Yes, the default scaffolding puts a parent selector in the child class' create/edit page.
I'm guessing it was just easier for them this way. It shouldn't be a multi-select though, just a pull-down single-select, as it's a One-to-Many.
As you've explained you wanted more of a Many-to-Many relationship, you might try adding:
static hasMany = [teams:Team]
to your Player class. I've found that Grails does better with bi-directional relationships. It's also useful to have when building search queries, and shouldn't require more than the one relationship table you'd already need.
If you're using Grails pre-v1.1, Many-to-Many relationships aren't directly supported, so even adding the static hasMany above won't be the complete solution, as you'll need to manage adding to the other list when you add to one direction. I haven't used v1.1 yet, so I can't talk about what is needed to specify the Many-to-Many in it.
I encountered the same problem using current version (v1.3.4) of Grails. Had to manually modify the create.gsp

Resources