Use Struts2 property tag in DisplayTags - struts2

I'm trying to render a table using DisplayTag. Everything works normally when I render a column in the usual manner:
<display:column property="id_material" title="ID" />
Now, i want one column to show 2 properties concatenated. So I tried using the < s:property > tag:
<display:column title="UNIDAD"><s:property value="property1"/> <s:property value="property2"/></display:column>
But no value is showed in the column. Is there an alternative way to do this?

You can use a decorator, get the row object properties and return the concatenation of both.
A quick example:
public class ExampleDecorator extends TableDecorator{
public String getConcatenatedProperties(){
Object object = getCurrentRowObject();
return object.getProperty1() + " " + getProperty2();
}}
Then you add a column in the display table:
<display:column property="concatenatedProperties" title="Properties" />
To use the decorator in the displaytag:
<display:table [..] decorator="org.example.ExampleDecorator" [...] >

Try to add uid attribute in table tag and then you can access current row in Struts2 via request attribute. See following code:
<display:table name="list" uid="row">
<display:column title="UNIDAD"><s:property value="#attr.row.property1"/> <s:property value="#attr.row.property2"/>
</display:column>
</display:table>

Related

How to build an edit form for a list of strings in Grails?

I have a Grails domain class with a list of strings in it, and I want to edit these strings. For the sake of simplicity let's assume that the list is fixed size. Here's what I have:
MyEntity.groovy:
class MyEntity {
String name
List variables = ['one', 'two', 'three']
static hasMany = [
variables: String,
]
}
_fields/myEntity/variables/_widget.gsp:
<g:textField name="variables[0]" value="${value[0]}" />
<g:textField name="variables[1]" value="${value[1]}" />
<g:textField name="variables[2]" value="${value[2]}" />
This renders text fields for each element in the list that are prefilled with the correct values. However, when I edit the values and sumbit the form my edits get discarded. What am I missing?
Ok, I found it myself. The input fields all need to have the name of the domain property, without any index:
<g:textField id="variables[0]" name="variables" value="${value[0]}" />
<g:textField id="variables[1]" name="variables" value="${value[1]}" />
<g:textField id="variables[2]" name="variables" value="${value[2]}" />

Grails default methods in controller

I am having a problem saving a domain instance in grails; The domainInstance that's passed to the default update method in my controller is NULL. The GSP page I am submitting from is not the default edit page. I have certain values from DB that need to be saved. I have the form tag defined on the page that contains the values I need to submit, as follows.
<g:form id="sampleForm" url="[resource:domainInstance, controller:'cntrlrName', action:'update']" method="PUT" >
I also have a version field which looks like this.
<g:hiddenField name="version" value="${domainInstance?.version}" />
My g:submit is as follows
<g:actionSubmit action="update" value="${message(code: 'default.button.update.label', default: 'Update')}" />
Why is my domain instance null? What am I missing?
This is the common mistake one could make. The attribute id in <g:form> tag is not the id attribute of HTML tags but it is the id to use in the link for default mapping of Grails i.e.
"/$controller/$action/$id" {}
So change your tag as:
<g:form name="sampleForm" id="${domainInstance.id}" controller="cntrlrName" action="update" method="PUT">
You can pass the domainInstance but I feel it is better practice to pass the id instead of the object. Try passing the id of the domain instance and then reading the object in the controller.
<g:form name="sampleForm" action="action" controller="controller" id="${domainInstance.id}" ></g:form>
// in controller
def resource = Domain.read(params.id)
another approach could be to pass the domainInstance as a hiddenField
<g:hiddenField name="resource" value="$domainInstance" />

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 render list of checkboxes

I've scoured the web for almost a day and can't seem to find a solution to my problem.
I have a lookup table called Hobby which has a bunch of hobbies in it (camping, hiking, biking, etc). The hobbies table is populated during the bootstrap. Grails creates a hobby table with an id, and description field.
I have a domain object called Applicant. An applicant can have zero or more hobbies. I've declared the domain like this:
class Applicant {
static hasMany = [hobbies:Hobby]
List <Hobby> hobbies = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(Hobby.class));
}
In my controller I'm using a command object for the page that will allow the applicant to select their hobbies. It is defined as:
class LifestyleCommand {
List <Hobby> hobbies = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(Hobby.class));
}
My gsp looks like this:
<g:each var="item" in="${Hobby.list()}" status="i">
<g:set var="newline" value="${(i % 3) == 0 ? 'newline' : ''}" />
<div class="formcheckbox columns3 ${newline}">
<g:checkBox name="hobbies_${item.id}" optionKey="id" value="${item.id}" />
<label>${item.description}</label>
</div>
</g:each>
The page will display all of the hobbies in the page correctly. However when I try to submit the form back to the controller the list in the LifeStyleCommand object is null. I'm not sure if my gsp has the g:checkBox variables set correctly, and I'm not sure if I declared the List in the command object correctly either. Once I get the data to be sent back to the controller, my next problem to overcome will be copying the data from the command object to the Applicant. Any help would be appreciated.
I've tried using just a plain List in the command but grails complains about type conversions when the form is submitted.
EDIT:
Here is what I got to work:
class Applicant {
static hasMany = [hobbies:Hobby]
//I removed the List <hobby>... code
...
}
My command object:
class LifestyleCommand {
Set <Hobby> hobbies;
}
gsp:
<g:each in="${Hobby.list()}" var="hobby">
<g:set var="checked" value="${ command?.hobbies.find{h->h.id == hobby.id } != null }" />
<g:checkBox value="${checked}" name="${ 'hobby' +'[' + hobby.id + ']'}"/>${hobby.description}</td>
</g:each>
And my new controller code:
Hobby.list().each{hobby->
if (params["hobby[${hobby.id}]"] == 'on') {
applicant.addToHobbies(hobby)
}
else if (applicant.getHobbies().contains(hobby)) {
applicant.removeFromHobbies(hobby)
}
}
Everything is working. There may be better ways, and I haven't done any refactoring yet but having it work is a starting point.
The problem is with your GSP. When you need a list of objects, you have to maintain a standard name for your checkbox:
<g:checkBox name="hobbies[$i].id" ... />
This will be mapped correctly to your command list.

Grails form data binding when another domain object is referenced in the form

How do I get Grails data binding to correctly bind referenced objects (such as Country in the example below)?
Given the following two Grails domain classes ..
class User {
String username
Country country
}
class Country {
String name
}
.. and the following HTML form ..
<g:form>
<g:textField name="user.username" value="${user.username}" />
<g:select name="user.country" from="${Country.list()}" optionKey="id" />
</g:form>
.. and the following code in the corresponding action ..
User user = new User(params["user"])
.. I would have hoped that user.username and user.country would get bind. However, it appears as if username.username gets bind, whereas user.country is not. What is the correct syntax to bind referenced objects (user.country in this example)?
The binding of the "country" property starts working if ..
<g:select name="user.country" from="${Country.list()}" optionKey="id" />
.. is changed to ..
<g:select name="user.country.id" from="${Country.list()}" optionKey="id" />
You should also look into command objects. They can validate and bind all of your parameters at once.

Resources