我找到了一個解決方案,但這只是因爲我的應用程序不再是一個標準的Roo應用程序。 無論如何,我會解釋我的解決方案,也許有人找到一種方法來適應標準的Roo應用程序。
這個想法是當required
屬性爲false
時,在下拉框中添加一個空選擇。 主要問題是如果沒有value
下拉框中有一個選項,dijti/dojo擴展將無法正確工作。 所以我的解決方案是給他們例如value
"null"
(<option value="null></option>
)。 在服務器端,必須將轉換數據庫ID(即正常值)的轉換器更改爲實體(通過從數據庫加載它)一點點 ,以便它將字符串"null"
轉換爲null
而不是實體。
但這是春天Roo的問題。 Roo使用自動註冊爲 (未記錄https://jira.springsource.org/browse/SPR-7461)的org.springframework.core.convert.support.IdToEntityConverter
,並嘗試將每個對象轉換爲實體(如果實體類爲靜態查找方法)。 我找不到修改其行爲的方法。
但我個人有很多運氣,因爲前段時間我改變了我的應用程序,它沒有那個靜態查找器,所以我有我自己的通用Id到實體轉換器,很容易改變。 轉換器將字符串轉換爲實體。如果字符串爲「null」,則返回null,否則將字符串轉換爲數字並通過此數字/ ID加載實體。
對於視圖,它接縫,必須擴展select.tagx
文件。
select.tagx
文件包含12種不同的方式來填充選擇框。
- 其中6人是多重選擇,所以他們可以保持他們的身份。
- 2的,如果不是多者爲殘疾形式結合,有一個必須選擇標籤
線75,130之後添加此塊,
<c:if test="${not required}">
<option value="null"></option>
</c:if>
...
<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>
現在它應該工作。
但它有一個小缺陷。如果有沒有發佈者的圖書,則空白下拉選項將不具有選擇屬性。 這並不壞,因爲它是最上面的選項,如果沒有選擇其他選項,它將顯示。
如果有人不能接受這個缺陷,那麼解決這個問題的一種方法是編寫一個自己的jsp標籤,擴展org.springframework.web.servlet.tags.form.Option
(做spring選項標籤的類)。 只有兩件事情,一個真正需要改變:
1)的方法isSelected(Object resolvedValue)
必須返回true,如果綁定狀態爲空(所以這種方法變得非常容易)
private boolean isSelected(Object resolvedValue) {
BindStatus bindStatus = getBindStatus();
return bindStatus == null || bindStatus.getValue() == null || bindStatus.getActualValue() == null;
}
2)如果標記呈現沒有或空的正文(方法renderDefaultContent
)呈現的html option
的內容應該是空的,但不是value
。 因此,必須將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>
「@ManyToOne(optinal = true)」對不對?它應該是「可選」的權利? ;) – bhagyas
@bhagyas你是對的這是一個錯字,我糾正了這個問題 – Ralph