编程语言
首页 > 编程语言> > java-如何在Spring Roo / Dojo中执行非强制性下拉框?

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