jefo
Feb 5th, 2007, 04:55 PM
Hi fellows, I'm experiencing a problem trying do make form:select work in a view that I have used spring:bind tags.
I have thwo select boxes, the leftone must have the options selected, in this case just one option, but I have other cases that I must be able to select more than one option. The rightone have all the options available.
Te code:
<table>
<tr><td>
<spring:bind path="news.channels">
<fmt:message key="cms.news.form.channels.selected"/><br/>
<select name="<core:out value="${status.expression}"/>" size="6">
<core:forEach var="c" items="${news.channels}">
<option value="<core:out value="${c.id}"/>"><core:out value="${c.path}"/></option>
</core:forEach>
</select>
<br/><font color="red"> <core:out value="${status.errorMessage}"/></font>
</spring:bind>
</td><td>
<input type="button" value="<<" onClick="copyLimited(form._channels, form.channels, 1);"><br/>
<input type="button" value=">>" onClick="removeSelected(form.channels);"><br/>
</td><td>
<fmt:message key="cms.news.form.channels.all"/><br/>
<select name="_channels" size="6">
<core:forEach var="c" items="${channels}">
<option value="<core:out value="${c.id}"/>"><core:out value="${c.path}"/></option>
</core:forEach>
</select>
</td></tr>
</table>
Was replaced by:
<table>
<tr><td>
<fmt:message key="cms.news.form.channels.selected"/>
<form:select path="channels" size="6" multiple="multiple">
<form:options items="${news.channels}" itemLabel="path" itemValue="id" />
</form:select>
<form:errors path="channels" cssClass="invalid" />
</td><td>
<button type="button" onclick="copyLimited(allChannels, channels, 1);"> « </button><br/>
<button type="button" onclick="removeSelected(channels);"> » </button>
</td><td>
<fmt:message key="cms.news.form.channels.all"/>
<select name="allChannels" id="allChannels" size="6" style="width: 312px;">
<core:forEach var="c" items="${channels}">
<option value="<core:out value="${c.id}"/>"><core:out value="${c.path}"/></option>
</core:forEach>
</select>
</td></tr>
</table>
With the spring:bind tag everthing works fine. I use this view to include and update values, without any problem.
The second aproaches works fine when I add some value in the first select box, but if a dont fill this box I have this error when my validator rejects the unfill value, it is mandatory:
java.lang.IllegalArgumentException: 'items' cannot be null.
at org.springframework.util.Assert.notNull(Assert.jav a:113)
at org.springframework.web.servlet.tags.form.OptionsT ag.setItems(OptionsTag.java:67)
I see that the news.channels are null after I submit the form and my validator rejects them, the thing that I don't understand is why this value becomes null after validation.
Here is my controller:
@Override
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
System.err.println("onsubmit...");
News news = (News) command;
if(news.getId() == null) {
news.setAuthor((User) WebUtils.getSessionAttribute(request, "user"));
contentService.addNews(news);
} else {
if(request.getParameter("channels") == null) {
news.setChannels(null);
}
if(request.getParameter("contents") == null) {
news.setContents(null);
}
contentService.updateNews(news);
}
return new ModelAndView(new RedirectView(getSuccessView(), true));
}
@Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
News news = new News();
String newsId = request.getParameter("id");
if(newsId != null) {
news = contentService.loadNews((Long) NumberUtils.parseNumber(newsId, Long.class));
} else {
// TODO refactoring create method that get the default contentsource, not the id=1 one
news.setContentSource(supportContentService.loadCo ntentSource(1l));
}
System.err.println("formBackingObject: " + news.getChannels());
return news;
}
and my custom editor:
public class CustomChannelsEditor extends PropertyEditorSupport {
private ChannelService channelService;
public CustomChannelsEditor(ChannelService channelService) {
this.channelService = channelService;
}
public String getAsText() {
System.err.println("CustomChannelEditor.getValue(): " + getValue());
if(getValue() == null) {
return "";
}
StringBuffer sb = new StringBuffer();
for (Iterator iterator = ((Collection)getValue()).iterator(); iterator.hasNext();) {
sb.append(((Channel)iterator.next()).getId().toStr ing());
}
return sb.toString();
}
@SuppressWarnings("unchecked")
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
Set<String> ids = StringUtils.commaDelimitedListToSet((String) text);
Set<Channel> values = new HashSet<Channel>(ids.size());
for (String id : ids) {
values.add(channelService.loadChannel(Long.valueOf (id)));
}
setValue(values);
}
}
}
My command class stantiates a set of channels:
public class Content implements Serializable {
private Long id;
private String title;
private String shortDescription;
private Date creationDate;
private Date lastUpdateDate;
private Date firstPublicationDate;
private Date lastPublicationDate;
private Set<Channel> channels = new HashSet<Channel>();
private Set<Content> contents = new HashSet<Content>();
private ContentSource contentSource;
private User author;
private char status;
//getters and setters...
I made some debugging and realize that my custom editor is not fired when the select box are unfill.
Any ideas, i'm completely lost about this?!?
Tks any help will be very very apreciate.
I have thwo select boxes, the leftone must have the options selected, in this case just one option, but I have other cases that I must be able to select more than one option. The rightone have all the options available.
Te code:
<table>
<tr><td>
<spring:bind path="news.channels">
<fmt:message key="cms.news.form.channels.selected"/><br/>
<select name="<core:out value="${status.expression}"/>" size="6">
<core:forEach var="c" items="${news.channels}">
<option value="<core:out value="${c.id}"/>"><core:out value="${c.path}"/></option>
</core:forEach>
</select>
<br/><font color="red"> <core:out value="${status.errorMessage}"/></font>
</spring:bind>
</td><td>
<input type="button" value="<<" onClick="copyLimited(form._channels, form.channels, 1);"><br/>
<input type="button" value=">>" onClick="removeSelected(form.channels);"><br/>
</td><td>
<fmt:message key="cms.news.form.channels.all"/><br/>
<select name="_channels" size="6">
<core:forEach var="c" items="${channels}">
<option value="<core:out value="${c.id}"/>"><core:out value="${c.path}"/></option>
</core:forEach>
</select>
</td></tr>
</table>
Was replaced by:
<table>
<tr><td>
<fmt:message key="cms.news.form.channels.selected"/>
<form:select path="channels" size="6" multiple="multiple">
<form:options items="${news.channels}" itemLabel="path" itemValue="id" />
</form:select>
<form:errors path="channels" cssClass="invalid" />
</td><td>
<button type="button" onclick="copyLimited(allChannels, channels, 1);"> « </button><br/>
<button type="button" onclick="removeSelected(channels);"> » </button>
</td><td>
<fmt:message key="cms.news.form.channels.all"/>
<select name="allChannels" id="allChannels" size="6" style="width: 312px;">
<core:forEach var="c" items="${channels}">
<option value="<core:out value="${c.id}"/>"><core:out value="${c.path}"/></option>
</core:forEach>
</select>
</td></tr>
</table>
With the spring:bind tag everthing works fine. I use this view to include and update values, without any problem.
The second aproaches works fine when I add some value in the first select box, but if a dont fill this box I have this error when my validator rejects the unfill value, it is mandatory:
java.lang.IllegalArgumentException: 'items' cannot be null.
at org.springframework.util.Assert.notNull(Assert.jav a:113)
at org.springframework.web.servlet.tags.form.OptionsT ag.setItems(OptionsTag.java:67)
I see that the news.channels are null after I submit the form and my validator rejects them, the thing that I don't understand is why this value becomes null after validation.
Here is my controller:
@Override
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
System.err.println("onsubmit...");
News news = (News) command;
if(news.getId() == null) {
news.setAuthor((User) WebUtils.getSessionAttribute(request, "user"));
contentService.addNews(news);
} else {
if(request.getParameter("channels") == null) {
news.setChannels(null);
}
if(request.getParameter("contents") == null) {
news.setContents(null);
}
contentService.updateNews(news);
}
return new ModelAndView(new RedirectView(getSuccessView(), true));
}
@Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
News news = new News();
String newsId = request.getParameter("id");
if(newsId != null) {
news = contentService.loadNews((Long) NumberUtils.parseNumber(newsId, Long.class));
} else {
// TODO refactoring create method that get the default contentsource, not the id=1 one
news.setContentSource(supportContentService.loadCo ntentSource(1l));
}
System.err.println("formBackingObject: " + news.getChannels());
return news;
}
and my custom editor:
public class CustomChannelsEditor extends PropertyEditorSupport {
private ChannelService channelService;
public CustomChannelsEditor(ChannelService channelService) {
this.channelService = channelService;
}
public String getAsText() {
System.err.println("CustomChannelEditor.getValue(): " + getValue());
if(getValue() == null) {
return "";
}
StringBuffer sb = new StringBuffer();
for (Iterator iterator = ((Collection)getValue()).iterator(); iterator.hasNext();) {
sb.append(((Channel)iterator.next()).getId().toStr ing());
}
return sb.toString();
}
@SuppressWarnings("unchecked")
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
Set<String> ids = StringUtils.commaDelimitedListToSet((String) text);
Set<Channel> values = new HashSet<Channel>(ids.size());
for (String id : ids) {
values.add(channelService.loadChannel(Long.valueOf (id)));
}
setValue(values);
}
}
}
My command class stantiates a set of channels:
public class Content implements Serializable {
private Long id;
private String title;
private String shortDescription;
private Date creationDate;
private Date lastUpdateDate;
private Date firstPublicationDate;
private Date lastPublicationDate;
private Set<Channel> channels = new HashSet<Channel>();
private Set<Content> contents = new HashSet<Content>();
private ContentSource contentSource;
private User author;
private char status;
//getters and setters...
I made some debugging and realize that my custom editor is not fired when the select box are unfill.
Any ideas, i'm completely lost about this?!?
Tks any help will be very very apreciate.