I have this bean class
Class Address {
private String addressId;
private Set<Location> setOfLocations;
// more attributes
//getters and setters
}
Class Location{
private Long locationId;
private String locationName
private String nearestHospital;
//getters and setters
}
in the jsp I have a textField controls for the Address class members, and also for Location class members one for locationName and nearestHospital.
the Address class members map normally because the model driven interface map them to their respective fields. the problem is how i can map the location textFields to a location object inside Set member of the Address class
Add new item to collection
Using type conversion and a list instead of a set, this will work to add a new item to the list:
<s:textfield name="locations[%{locations.size()}].locationName"/>
If you want to use a set, then I don't know how to achieve what you want without spending some time digging, but you will want to start here.
Display and edit existing collection items
On the other hand, if you were to want to be able to display and edit an existing collection, then this should work if you use a list instead of a collection:
<s:iterator var="listItem" value="yourList" status="listStatus">
<s:set name="paramName">yourList[${ listStatus.index }].someField</s:set>
<s:textfield name="%{#paramName}" value="%{#listItem.someField}"/>
</s:iterator>
Here, your model would have a list called yourList. The items in yourList contain a field called someField. We are able to set the value onto the fields by setting the request parameter name to be in the form yourList[2].someField so that OGNL will evaluate this and set the parameter value onto the someField field of item 2 of yourList.
Using your classes as you show them above but with changing the locations to a list, we would have:
<s:iterator var="location" value="listOfLocations" status="locationStatus">
<s:set name="paramName">listOfLocations[${ locationStatus.index }]</s:set>
<s:hidden name="%{#paramName}.locationId" value="%{#location.locationId}"/>
<s:textfield name="%{#paramName}.locationName" value="%{#location.locationName}"/>
<s:textfield name="%{#paramName}.nearestHospital" value="%{#location.nearestHospital}"/>
</s:iterator>
Or, if you are using JSTL, this will do the same:
<c:forEach var="location" items="${ listOfLocations }" varStatus="locationStatus">
<s:set name="paramName">listOfLocations[${ locationStatus.index }]</s:set>
<s:hidden name="%{#paramName}.locationId" value="%{#location.locationId}"/>
<s:textfield name="%{#paramName}.locationName" value="%{#location.locationName}"/>
<s:textfield name="%{#paramName}.nearestHospital" value="%{#location.nearestHospital}"/>
</c:forEach>
Related
I'm using Grails version 2.4.4 and postgresql. When I run app, I see error message Cannot get property 'myname' on null object. I know that table is not empty and database connected correctly, because I can upload and see data using scaffolding.
domain class code:
class My_table {
//Integer id
String myname
static constraints = {}
}
Controller code:
class My_tableController {
def index() {
def my_table = My_table.list()
[my_table:my_table]
}
My index.gsp file:
<g:select name="name" from="${my_table}"/><br/>
<label>${my_table.myname} </label><br/>
In the form that I see the error happens in this line: <label>${my_table.myname} </label><br/>.
Here you are calling the property name out of context
<g:select name="name" from="${my_table}"/><br/>
<label>${my_table.myname} </label><br/>
You get an error because my_table is a list of My_table instances and does not have a property named name.
A way to fix this problem could be:
<select name="name">
<g:each in="${my_table}" var="table">
<option value="${table.name}">${table.name}</option>
</g:each>
</select>
Also remember label tags are not valid inside a select, as you can read Permitted content Zero or more <option> or <optgroup> elements. in https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select
Table is a reserved word in most databases. Either change the name of the class and property or map them to something else that is not reserved:
static mapping = {
table 'my_table'
}
Adding the column named table to a table named table is problematic because in the static mapping block a method named table already exists. Newer versions of grails have an ORM mapping block that is more flexible.
static mapping = {
table 'my_table'
table column: 'my_table' // unsure if this would work since it overlaps with the other mapping method
}
I have a address entity like this:
#Entity
public class Address implements java.io.Serializable {
#Id #GeneratedValue(strategy = IDENTITY)
private Long id;
#Size(max = 100)
private String street;
#Size(max = 15)
private String nr;
#Field
#Size(min = 1, max = 20) #NotBlank
private String city;
}
This is part of several other entities. For one such entity the address is optional.
I have a view where our users can edit the whole entity via several form inputs, including several address fields.
To be able to edit the address, I initialize the parent entity with an empty address entity.
Now the problem is: I don't want to persist an Address on the entity when all address fields are empty. For that to work, I need to skip validation for the entity if (and only if) all fields of Address are empty. How do I do that in the most elegant way?
What I'm currently doing is to skip bean validation altogether with <o:validateBean disabled="true" /> for the submit button, setting the address to null if it comes out empty. But this sounds like a total hack as it disables all validation in all cases. How can I do better?
You can just use EL in disabled attribute of <f:validateBean> (and <o:validateBean>). You can use EL to check if any of those fields have been filled. You can use binding attribute to reference a component in EL. You can check if a field has been filled by checking the value of the request parameter associated with component's client ID.
Then, to disable bean validation on those fields when #{addressIsEmpty} evaluates true, it's easier to use <f:validateBean> instead of <o:validateBean> as the former can be used to wrap multiple input components.
So, all with all, this should do:
<c:set var="addressIsEmpty" value="#{empty param[street.clientId] and empty param[nr.clientId] and empty param[city.clientId]}" />
<f:validateBean disabled="#{addressIsEmpty}">
<h:inputText binding="#{street}" value="#{bean.address.street}" />
<h:inputText binding="#{nr}" value="#{bean.address.nr}" />
<h:inputText binding="#{city}" value="#{bean.address.city}" />
</f:validateBean>
The <o:validateBean> is only easier to use if you intend to control it on a per-input or per-command basis.
Cross validation of multiple fields can be a tough issue. But in this situation it is not validation per se that bothers you in the first place but rather possibility to nullify some instance on some condition in your bean before you'd persist the entity.
The most straightforward way would be to mark all fields associated with Address entity as required="false" in your view not to care of fields being filled in (or just omit it as it's the default) and do all the checks of, and modifications to the placeholder in your action method, right before calling your EJB service. Like so:
public String save() {
//do some checks
if((entity.getAddress().getStreet() == null) && ...) {
//assign address to null
entity.setAddress(null);
}
entityService.persist(entity);
return "success";
}
I am new to struts2 and facing one issue.
I have following datastructure.
class Employee extends actionsupport{
Private List<Address> address;
....getters and setters
}
class Address {
private String street_name;
Private City_name;
......and so on
... getters and setters
}
how to iterate over this list in JSP using <s:iterate> tag. I tried many combination but some way it is not working for me.
I believe the best way is to use Struts2 iterator tag which needs to provide collection as a data-source to iterator over.
<s:iterator value="address">
<s:property value="street_name"/>
<s:property value="City_name"/>
//so on
</s:iterator>
When Iterator will iterator over the address it will place the object (Address in your case) on the top of value stack and you can refer to these properties directly as described above
<s:iterator value="%{address}" var="addr">
<s:property value="%{street_name}"/>
<s:property value="#addr.street_name"/>
</s:iterator>
I'm trying to create form for editing entity object when selected from datatable. So when user clicks commandButton in datatable, myBean.person property is filled with appropriate person object. Person has "status" property.
I'd like to validate edit form with different validation groups according to value of "status" property. Is this possible?
I created two different validation groups:
#Entity
public class Person{
private String status;
...
#NotNull(message = "{person.null.name}", groups = PersonNew.class)
private String name;
#NotNull(message = "{person.null.code}", groups = PersonActive.class)
private String code;
}
I'd like to validate form before saving and when status is "new", then name property should be set. When status is "active", then code property should be set.
I have jsf page:
<h:form id="personEdit">
<h:inputText value="#{myBean.person.name}" />
<h:inputText value="#{myBean.person.code}" />
... other fields for other properties ...
<h:commandButton value="Save" action="#{myBean.save}" />
</h:form>
I tried to use <f:validateBean /> tag with dynamicaly set validationGroups attribute, but method that returned validationGroups was called before actual person object was retrieved. So I couldn't decide according to Person.status property.
So is it possible to define PersonNew as validation group if person has status "new", otherwise define PersonActive as validation group?
Thanks for any help.
If you use Hibernate Validator than looks like #GroupSequenceProvider should satisfy your needs:
The #GroupSequence annotation is a standardized Bean Validation annotation [...] it allows you to statically redefine the default group sequence for a class. Hibernate Validator also offers a custom, non standardized annotation - org.hibernate.validator.group.GroupSequenceProvider - which allows for dynamic redefinition of the default group sequence.
See official manual.
Is it possible to convert different paremeters into one object on your action?
Say from my html form, I pass in variables, "firstname", "lastname". Can I write a type converter that will convert those into a Person object on my action?
I didn't see any examples of this, and I don't see API. I don't see how I can access the value stack in the StrutsTypeConverter to get to the other variables.
Thanks!
Example :
// JavaBeans
public class Person {
#Getter #Setter private String firstname;
#Getter #Setter private String lastname;
}
// Action
#Setter private Person person;
// form
<s:form>
<s:textfield name="person.firstname" />
<s:textfield name="person.lastname" />
</s:form>
Similar example : vaannila : Domain Object as JavaBeans Property
I am agree what lschin said.you can use the build in OGNL and value stack combination to achieve what you want.still if u need some specific type conversion machanism here are the details from the Struts2 docs
Struts2 Type Conversion