How do I save a composite field value in Grails GSP? - grails

I have a composite domain object as follows:
class Person
{
static embedded = ['forSale']
Boolean isSelling
House forSale
}
class House
{
Integer numBedrooms
}
I have a select control for the numBedrooms as follows:
<tr class="prop">
<td valign="top" class="name">
<label for="numBedrooms"><g:message code="person.numBedrooms.label" default="Num Bedrooms" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance, field: 'forSale.numBedrooms', 'errors')}">
<g:select name="numBedrooms" value="${fieldValue(bean: personInstance, field: 'forSale.numBedrooms')}"
noSelection="${['null':'Select a number...']}"
from="${1..6}"
/>
</td>
</tr>
Notice that I am using forSale.numBedrooms in the fieldValue on the select. I haven't been able to produce scaffolded code for this to take a look at how it is supposed to be done because the create view which gets generated by create-views contains no references to the fields in the forSale House object.
I also haven't been able to turn up any exampes of composite fields being accessed via GSP, so this is a bit of a guess. In any case the GSP page renders without errors, although that may be because I haven't been able to save any data.
I send the value of numBedrooms back as part of a URl query string...
&numBedrooms=2
When I do this the save code in my controller is failing silently - at least nothing ever gets written to the database. I have switched on debug logging for pretty much everything but I get no messages in the log which suggest anything is wrong, although something obviously is.
If I remove the numBedrooms parameter from the query string then my save proceeds as normal, so I am guessing it is something to do with resolving numBedrooms.
Any clue what I am doing wrong and what I can do to track down my problem?

What I do is generate-all for the House Domain then copy and paste the GSP code and remove the files once I am done. I have also found it smarter to create templates to edit the House domain in the case where I am using the House domain later on.
For you GSP you need something like this (Notice the name attribute)
<tr class="prop">
<td valign="top" class="name">
<label for="forSale.numBedrooms"><g:message code="house.numBedrooms.label" default="Num Bedrooms" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance.forSale, field: 'numBedrooms', 'errors')}">
<g:select name="forSale.numBedrooms" value="${fieldValue(bean: personInstance.forSale, field: 'numBedrooms')}"
noSelection="${['null':'Select a number...']}"
from="${1..6}"
/>
</td>
</tr>
In your param string you need *forSale*.numBedrooms=2. this code will work with person.properties = params or new Person(params).
The embedded "instruction" only tells Hibernate to include the parameters in the same table they are still seperate Domain classes. It will probably generate a table for the domain even though you may never use it.
Hope this helps.

Related

Thymeleaf - if checked do something

I have a simple table and I have checkbox inside that table. If checkbox is selected I want to display other features.
My code:
<table>
<tr th:each="obj,iterationStatus : ${objs}">
<td th:text="${obj.name}"></td>
<td><input type="checkbox" name="firstcheckbox"></td>
<td th:if="isChecked">
<!-- do something -->
</td>
</tr>
</table>
How I do this without using javascript and backbean?
In this case you have two options, the first option you don't want but is not a bad option is using Javascript: creating a function called isChecked.
Otherwise, you can know if a checkbox is checked with thymeleaf in the case you are in a form which calls itself. You could do something like if(firstcheckbox != null) and, of course, your checkbox would have a value <input type="checkbox" name="firstcheckbox" value="value">. Finally, you must add as attribute in your model: model.addAttribute("firstCheckbox", firstCheckbox);

Capybara: Pulling in multiple Radio button options

Im running into an issue, and I think the issue is with how my page.all is pulling radio button questions in.
So here is the HTML for the table itself (Multiple questions with 5 radio button choices a piece):
<table class="table table-striped table-stuff table-collapsible">
<colgroup>
<thead>
<tbody>
<input id="0_answer_question_id" value="9966" name="response[answers][0][answer_id]" type="hidden">
<tr>
<td class="heading">
<td class="option">
<div class="radio-inline radio-inline--empty">
<input id="question_1_1" value="1" name="response[answers_attributes][0][answer_opinion]" type="radio">
<label for="question_1_1">Strongly Disagree</label>
</div>
</td>
<td class="option">
<td class="option">
<td class="option">
<td class="option">
</tr>
<input id="response_1_question_id" value="9966" name="response[answers_attributes][1][answer_question_id]" type="hidden">
<tr>
<input id="response_1_id" value="<a number>" name="response[answers_attributes][1][id]" type="hidden">
<Same as above repeated 5 times with numbers changed>
</tbody>
</table>
Im using:
page.all('table.table-stuff tbody tr', minimum: 6).each do |row|
row.all("td label").sample.trigger('click')
end
To get each row and select one from it. HOWEVER, I notice "sometimes" a row will not have one selected. My theory is the "heading" (which has a <label> itself is accepting one of the clicks perhaps? (since from my understanding of how page.all works it's grabbing every tbody tr within the table...but is maybe grabbing the heading too? (since it contains a td label?)
Also when a table is named something like table table-striped table-stuff table-collapsible...how can you tell what the actual table "name" is? (I didn't write this website, just doing tests for it). When putting it in the page.all('table.<etc>')?
If the heading td (it's not expanded in your example) also contains a label element (so it would be included in the results of your all call) then you just need to change the CSS selector so it wouldn't be included - something like
row.all("td.option label").sample.trigger('click') # only choose labels contined in tds with the class of 'option'
or
row.all("td:not(.heading) label").sample.trigger('click') # choose labels contained in tds without the class of 'heading'
On your second question about table names, I don't really understand what you're asking. Tables don't have name attributes, they could have an id attribute or a caption containing some text which could then be used to find them with capybara via find(:table, 'id or caption text') or within_table('id or caption text') { code to execute within scope of the table }. Rather, you seem to be talking about the classes on the element which are specified in a CSS selector with '.'. Therefore a CSS selector to match a table element with all the classes you listed would be - 'table.table.table-striped.table-stuff.table-collapsible'
Note: If you're sure there's always only 5 choices you could add the :count option to your find to make sure your selector is only finding those items
row.all("td.option label", count: 5).sample.trigger('click')

Struts2 tags: get a request attribute whose name is itself a value of another request attribute

I have a list of table names in a request attribute, "BillSummaryTables". I am iterating through the list and I want to use each table name to get a request attribute for that particular table name. Corresponding to each table name I have another list in request attribute and I want to iterate through that.
This is what I am doing.
<s:iterator value='#request.BillSummaryTables' var="tableName" status="itStatus">
<div class="contentbox" role="content">
<table class="rpt">
<s:iterator value="#request.get('%{#tableName}').getData()" var="ocRow" status="itStatus">
<tr style="border:1px solid #CCCCCC">
<s:iterator value='#ocRow' var="cell" status="itStatus2">
<td>
<s:property value="#cell.getValue()"/>
</td>
</s:iterator>
</tr>
</s:iterator>
<tr>
<s:iterator value="#request.get('%{#tableName}').getData()" var="ocTotal">
<td>
<s:property value="#ocTotal"/>
</td>
</s:iterator>
</tr>
</table>
</div>
</s:iterator>
I have also tried
#request[<s:property value="#tableName" />].getData()
and
#request['<s:property value="#tableName" />'].getData()
and
#request.%{#tableName}
But nothing is returned in any case.
However, this code works fine if I hard code the values.
i.e. if i use: #request['other_charges'].getData()
Note: I am able to retrieve the list of tableName (#request.BillSummaryTables).
#1) You are using three nested iterators, but both the first and the second have an instance of IteratorStatus called itStatus; they must have different names to work.
#2) If the Lists corresponding to the Table name is, effectively, a List, then you should iterate the list, not the getData() stuff (what is that ?)
#3) Why using request ? why not simply using an HashMap on the Action (with the getter), adding elements dynamically using table names as key ?
#4) This #request[<s:property value="#tableName" />].getData() will obviously not work if put inside another Struts2 tag, like an Iterator (cannot nest Struts2 tags).
However, try something like this (I stripped the second iterator, make it running before, then add stuff), and see if it works (and what it prints):
<s:iterator value='#request.BillSummaryTables' var="tableName" status="statusAllTables">
<div class="contentbox" role="content">
<br/>==== START DEBUG ====
<br/>Current table name: [<s:property value="#tableName"/>]
<br/>Corresponding request object: [<s:property value="#request['%{#tableName}']"/>]
<br/>getData on that object: [<s:property value="#request['%{#tableName}'].getData()"/>]
<br/>===== END DEBUG =====
<table class="rpt">
<s:iterator value="#request['%{#tableName}'].getData()" var="ocRow" status="statusThisTable">
<tr style="border:1px solid #CCCCCC">
<s:iterator value='#ocRow' var="cell" status="statusThisField">
<td>
<s:property value="#cell.getValue()"/>
</td>
</s:iterator>
</tr>
</s:iterator>
</table>
</div>
</s:iterator>
EDIT
Ok, but then why are you using request.setAttribute ? Actions are created per-request... just use a private List<MyObjects> myObjects with its getter (public List<MyObject> getMyObjects()), and call it from JSP with <s:iterator value="myObjects"> (in your case, <s:iterator value="myObjects.data">.
Please note that .getData() in OGNL should become .data (i didn't noticed it before), removing the get, lowering the first letter of the method, and removing round brackets...
Retry and let us know.

Struts2 based quiz application using DB for getting questions and storing results

jsp file
<s:iterator value="questions" status="status">
<table border="3px" bgcolor="yellow">
<tr bgcolor="white" >
<td nowrap><s:property value="QuestionNumber"/></td>
<td nowrap><s:property value="Question"/></td>
</tr>
<tr>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="1"/><s:property value="Option1"/></td>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="2"/><s:property value="Option2"/></td>
</tr>
<tr>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="3"/><s:property value="Option3"/></td>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="4"/><s:property value="Option4"/></td>
</tr>
</table>
<s:hidden> </s:hidden>
</s:iterator>
<s:hidden id="answers" value="answers"/>
<s:submit name="submit" onclick="submitform()"/>
</s:form>
property values are being populated from DB using the Action class.
My problem is that i want to collect the list answers for a quiz and get it to the java classes for evaluation of score. Im not able to get any idea as how to do it
My DB has Questions table with the list of questions with options and correct answer.
I have a Question Bean Object.
You have an Action with a private List<Question> questions;, with Getter and Setter.
You populate your JSP reading the list from the Getter.
You can post that list back from the JSP to the Action's Setter by using OGNL for keeping informations on lines detail.
To do this, use Struts tags (<s:radio instead of <radio ) and set a name including the index of the line.
For example, with a textfield, instead of
<s:iterator value="questions" status="status">
<s:textfield name="question" />
</s:iterator>
use something like (untested, maybe some adjustments needed)
<s:iterator value="questions" status="status">
<s:textfield name="questions[%{#status.index}].question" />
</s:iterator>
Just adapt this for your radio case,
and in the Action you will receive your List fully populated.
(You can even validate a list posted like this usign Visitor validator: not your case, but it's worth knowing).
there are many ways to do this. the easiest way is to implement ParameterAware, checkout the link ParameterAware, then you can get all your parameters like this: (I'm assuming, QuestionNumber is a parameter of your bean question)
String param1 = parameters.get(question.getQuestionNumber);
you can put this line in a loop, so you can get all your parameters...

issues with <g:each> tag iteration in Grails

I'm new to grails and I am trying to display all the data of a domain class from the database in a table. When I open the gsp file my table is blank. I'm not sure what I am doing wrong since I have been following every tutorial exactly with the same syntax. My domain class name is "Test" and here is my code for the table:
<g:each var="test" in="${tests}">
<tr>
<td>
${test.testName}
</td>
<td>
${test.numberofQuestions}
</td>
<td>
${test.responseType}
</td>
</tr>
</g:each>
If you are just trying to bring back all of your "Test" domain objects you would do something like this:
<g:each var="test" in="${com.mypackage.Test.list()}">
or
<g:each var="test" in="${com.mypackage.Test.listOrderByTestName()}">
if you wanted them in order by testName (be sure to use the actual package name in place of com.mypackage).
If you are trying to pass a tests variable into the GSP to be used as jonaldomo said in the comment we will need more information.

Resources