Convert automatically all forms to Grails Fields Plugin - grails

With Grails Fields Plugin you can write an actually shorter, cleaner, DRY code:
<bean:withBean beanName="person">
<bean:field property="username" label="Login Name:"/>
<bean:field property="userRealName" label="Full Name:"/> >
</bean:withBean>
The code above would do the same than the following:
<tr class="prop">
<td valign="top" class="name"><label for="username">Login Name:</label></td>
<td valign="top" class="value ${hasErrors(bean: person, field: 'username', 'errors')}">
<input type="text" id="username" name="username" value="${person.username?.encodeAsHTML()}"/>
</td>
</tr>
<tr class="prop">
<td valign="top" class="name"><label for="userRealName">Full Name:</label></td>
<td valign="top" class="value ${hasErrors(bean: person, field: 'userRealName', 'errors')}">
<input type="text" id="userRealName" name="userRealName" value="${person.userRealName?.encodeAsHTML()}"/>
</td>
</tr>
But, must I change all my already written code manually?

If I were you, I would have stuck to one word
CONSISTENCY
I would rather convert all of them using the plugin or do not use the plugin and convert none. So that in future, I would not have to deal with two types of handling. On the other hand, if you have a lot of views to be converted and you have a short deadline, then I would add this task to my backlog.
But again, it differs from person to person. This was my opinion. I hope this could be useful.

Grails fields plugin have an option for scaffolding, so at least you can regenerate your scaffolded code.
I agree with #dmahapatro about the consistency of the code, if you choose to use the plugin, it's an effort that must be made, to make all your views have the same pattern.

Related

Is there a way for me to strip away div classes and other CSS stuff when generating grails views?

Well, there goes my question. I really don't like the UI, and if there was a way to auto generate only the essential things like the fields but no divs and classes. I know about removing the css, but I really just want the raw html like what rails gives me. Anybody know how?
For example, grails generate-views myStuff generates code that looks like this:
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="name">Name:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:feedback,field:'name','errors')}">
<input type="text" id="name" name="name" value="${fieldValue(bean:feedback,field:'name')}"/>
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="feedback">Feedback:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:feedback,field:'feedback','errors')}">
<input type="text" id="feedback" name="feedback" value="${fieldValue(bean:feedback,field:'feedback')}"/>
</td>
</tr>
</tbody>
</table>
When I'm only interested in getting this:
<input type="text" id="name" name="name" value="${fieldValue(bean:feedback,field:'name')}"/>
<input type="text" id="feedback" name="feedback" value="${fieldValue(bean:feedback,field:'feedback')}"/>
Well, I could always do stuff manually and not auto-generate, but, no it's not practical when the fields are too many. :(
Use the install-templates command to install the templates. Then you can edit/modify the templates to meet your needs.

Struts2 s:label issue

We need to display only 1 of the labels depending on condition. This is done through Javascript. That works fine, but the issue is we get a 508 compliant error saying 1 form element has 2 labels. The issue is with "for" in the table. Removing it also shows a 508 error. I tired to change the second label for to for="org.dateOfReg", but still the same. Is there a way to have only 1 label and pass the "for" and "name" values dynamically from javascript? Or is there any other option? Please help. Appreciate it a lot.
<tr id="showDates">
<td id="TypeDate1"><s:label for="dateOfReg" name="dateofReg" value="Date of Interest" /><span class="required" >*</span> :</td>
<td id="TypeDate2"><s:label for="dateOfReg" name="dateofReg" value="Date of Completion" /><span class="required" >*</span> :</td>
<td id="typeDatePick">
<sj:datepicker showButtonPanel="true" id="dateOfReg" name="org.dateOfReg" displayFormat="mm/dd/yy" label="Date of Interest" changeMonth="true" changeYear="true" size="7"/>
</td>
</tr>
Thanks
Harry
Here is what you can do to resolve this. Just have one label and change its innerHTml using JavaScript instead of hiding the label.
<tr id="showDates">
<td id="TypeDateLabel"><s:label for="dateOfReg" name="dateofReg" value="Date of Interest" /><span class="required" >*</span> :</td>
<td id="typeDatePick">
<sj:datepicker showButtonPanel="true" id="dateOfReg" name="org.dateOfReg" displayFormat="mm/dd/yy" label="Date of Interest" changeMonth="true" changeYear="true" size="7"/>
</td>
</tr>
<script language="javascript">
function TriggerToChangeLabel(triggerCondition)
{
if (triggerCondition)
$("dateOfReg").innerHtml = "Date of Interest";
else
$("dateOfReg").innerHtml = "Date of Completion";
}
</script>
But keep in mind that even though it makes the code 508 compliant; Dynamically changing the label text goes against the spirit of the accessibility. Better way to implement the same is it to have two date fields ("Date of Interest" and "Date of Completion"). Upon submission enforce "required" edit on one of the field based on the condition you have for the label change.

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.

Grails GSP doesn't generate intended HTML under Geronimo

When running my Grails 1.1-M2 app as a WAR under Geronimo 2.1.4 (jetty6, javaee5), the HTML generated from the GSPs do not include my dynamic content.
Specifically, this GSP snippet:
<tr class="prop">
<td valign="top" class="name">
<label for="type">
<g:message code="album.type.label" default="Type" />
</label>
</td>
<td valign="top" class="value ${hasErrors(bean:albumInstance,field:'type','errors')}">
<g:select from="${AlbumType?.values()}" value="${albumInstance?.type}" name="type" ></g:select>
</td>
</tr>
...produces this HTML when running under Geronimo:
<tr class="prop">
<td valign="top" class="name">
<label for="type">
Type
</label>
</td>
<td valign="top" class="value ">
<select name="type" id="type" ></select>
</td>
</tr>
...however when running as 'grails run-app' or 'grails run-war', this, correct HTML is produced:
<tr class="prop">
<td valign="top" class="name">
<label for="type">
Type
</label>
</td>
<td valign="top" class="value ">
<select name="type" id="type" >
<option value="EP" >EP</option>
<option value="LP" >LP</option>
<option value="SINGLE" >SINGLE</option>
</select>
</td>
</tr>
AlbumType.groovy is defined in src/groovy as:
public enum AlbumType {
EP,
LP,
SINGLE
}
I've turned on all logging within Grails and don't see any error or exceptions. This issue is confusing as I only see it while running my Grails WAR under Geronimo. Granted, I haven't tried any other app servers though it is curious that everything works fine with 'grails run-app' and 'grails run-war'.
Any ideas as to the problem?
I would highly recommend keeping code out of the the default package and putting it into a good package structure. I suspect this is your issue.

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