java-如何在Spring Roo / Dojo中执行非强制性下拉框?
作者:互联网
在Spring Roo(1.1.5)中,我有一个实体“ Book”,它可以引用一个实体“ Publisher”.
class Book {
@ManyToOne(optional=true)
Publisher publisher
}
现在,我有了Roo生成的Controller和JSPX文件.
在GUI中,用于创建和更新Book的是Roo生成的下拉框(由dijit.form.FilteringSelect装饰)以选择发布者.
但是用户必须选择发布者;没有“空”字段!
我的第一个尝试只是在列表中添加一个空值,该值代表下拉框的选项.
但这失败了. (java.lang.IllegalArgumentException:Bean对象不能为null)-因此,这可能是错误的方式.
因此,在尝试自行扩展select.tagx文件之前,我想问问是否有人已经解决了这个问题(在Spring Roo / Dojo中有一个可选的下拉菜单),或者我完全出错了,应该可以在正常情况下没有新的东西吗?
解决方法:
我找到了一个解决方案,但这仅能有效,因为我的应用程序不再是标准的Roo应用程序.
无论如何,我将解释我的解决方案,也许有人找到一种方法来使其适合标准Roo应用程序.
想法是,当required属性为false时,在下拉框中添加一个空选择.
主要问题在于,如果下拉框中只有一个选项没有值,那么dijti / dojo扩展名将无法正常工作.
因此,我的解决方案是给它们例如值“ null”(< option value =“ null>< / option>)).
在服务器端,必须稍微更改将数据库ID(即正常值)转换为Entity(通过从数据库加载)的转换器,
以便将字符串“ null”(而不是实体)转换为null.
但这就是Spring Roo的问题. Roo使用了自动注册的org.springframework.core.convert.support.IdToEntityConverter
(未记录https://jira.springsource.org/browse/SPR-7461),并且如果实体类为静态查找器方法,则会尝试将每个对象转换为实体.
我发现没有办法修改其行为.
但是我个人很幸运,因为前一段时间我更改了没有静态查找器的应用程序,所以我有自己的易于更改的通用ID到实体转换器.
转换器将String转换为Entity.如果String为“ null”,则返回null,否则将String转换为数字并按此数字/ id加载Entity.
对于该视图,它表明必须扩展select.tagx文件.
select.tagx文件包含12种不同的方式来填充选择框.
>其中6个用于多选,因此它们可以保持原样.
> 2个(如果不是多个)用于禁用表单绑定,则必须在select标记后立即添加此块
75、130行,
<c:if test="${not required}">
<option value="null"></option>
</c:if>
>其他4个稍微复杂一点
…
<form:select id="_${sec_field}_id" items="${items}" path="${sec_field}" disabled="${disabled}" />
...
<form:select id="_${sec_field}_id" items="${items}" path="${sec_field}" disabled="${disabled}" itemLabel="${sec_itemLabel}"/>
...
<form:select id="_${sec_field}_id" items="${items}" path="${sec_field}" disabled="${disabled}" itemValue="${fn:escapeXml(itemValue)}" />
...
<form:select id="_${sec_field}_id" items="${items}" path="${sec_field}" disabled="${disabled}" itemValue="${fn:escapeXml(itemValue)}" itemLabel="${sec_itemLabel}"/>
他们一个需要用替换完整的标签(我将仅在最后4个示例中对其进行演示,但是另一个相似,除了必须删除itemVlaue和itemLabel参数).
<form:select id="_${sec_field}_id" path="${sec_field}" disabled="${disabled}">
<c:if test="${not required}">
<option value="null"></option>
</c:if>
<form:options items="${items}" itemValue="${fn:escapeXml(itemValue)}" itemLabel="${sec_itemLabel}"/>
</form:select>
现在应该可以了.
但这有一个小缺陷.如果有一本没有出版商的书,则空的下拉选项将没有select属性.
这还不错,因为它是最上面的选项,如果没有选择其他选项,则会显示出来.
如果某人不能接受此缺陷,那么解决此问题的一种方法是编写自己的jsp标记,扩展org.springframework.web.servlet.tags.form.Option(执行spring选项标记的类).
真正需要更改的只有两件事:
1)如果绑定状态为null,则isSelected(Object resolveValue)方法必须返回true(因此此方法非常容易)
private boolean isSelected(Object resolvedValue) {
BindStatus bindStatus = getBindStatus();
return bindStatus == null || bindStatus.getValue() == null || bindStatus.getActualValue() == null;
}
2)如果标记呈现时没有主体或主体为空(方法renderDefaultContent),则呈现的html选项的内容应为空,但不应为值.
因此,必须将renderOption(SpecialWay)方法的第二个参数设置为固定为空字符串.
@Override
protected void renderDefaultContent(TagWriter tagWriter) throws JspException {
Object value = this.pageContext.getAttribute(VALUE_VARIABLE_NAME);
renderOptionSpecialWay(value, "", tagWriter);
}
但是,由于isSelected方法是私有的并且不能被覆盖,因此必须复制renderOption(可以重命名)并必须对其进行更改,以便它调用“新” isSelected方法.必须对两个方法renderDefaultContent和renderFromBodyContent进行相同的操作,因为renderOption也是私有的.
因此,有人提出了此类:
public class NullOptionTag extends OptionTag {
@Override
protected void renderDefaultContent(TagWriter tagWriter) throws JspException {
Object value = this.pageContext.getAttribute(VALUE_VARIABLE_NAME);
renderOptionSpecialWay(value, "", tagWriter);
}
@Override
protected void renderFromBodyContent(BodyContent bodyContent, TagWriter tagWriter) throws JspException {
Object value = this.pageContext.getAttribute(VALUE_VARIABLE_NAME);
String label = bodyContent.getString();
renderOptionSpecialWay(value, label, tagWriter);
}
private void renderOptionSpecialWay(Object value, String label, TagWriter tagWriter) throws JspException {
tagWriter.startTag("option");
writeOptionalAttribute(tagWriter, "id", resolveId());
writeOptionalAttributes(tagWriter);
String renderedValue = getDisplayString(value, getBindStatus().getEditor());
tagWriter.writeAttribute(OptionTag.VALUE_VARIABLE_NAME, renderedValue);
if (isSelected(value)) {
tagWriter.writeAttribute("selected", "selected");
}
if (isDisabled()) {
tagWriter.writeAttribute("disabled", "disabled");
}
tagWriter.appendValue(label);
tagWriter.endTag();
}
private boolean isSelected(Object resolvedValue) {
BindStatus bindStatus = getBindStatus();
return bindStatus == null || bindStatus.getValue() == null || bindStatus.getActualValue() == null;
}
}
下一步是将此类添加到标签库定义中,以便可以在select.tagx中使用它
<form:select id="_${sec_field}_id" path="${sec_field}" disabled="${disabled}">
<c:if test="${not required}">
<formExtension:nulloption value="null"></formExtension:nulloption>
</c:if>
<form:options items="${items}" itemValue="${fn:escapeXml(itemValue)}" itemLabel="${sec_itemLabel}"/>
</form:select>
标签:spring-roo,dojo,spring,java 来源: https://codeday.me/bug/20191102/1990483.html