2

我有一个从 selectonemenu 设置的字符串。菜单中的值取决于另一个菜单中的选择,并使用 JavaScript 填充。前端一切正常(菜单适当更新等),但是当我们提交更改时,没有设置字符串。菜单有一个转换器,并且正在调用 getAsObject。有人知道为什么没有设置字符串吗?

编辑.jspx

<h:selectOneMenu value="#{detectorInstance.type}" converter="detectorConverter" onchange="updateSubTypes(this, '#{applicationName}')">
    <s:selectItems value="#{detectors.detectors}" var="detectorSelection" label="#{detectorSelection.name}" noSelectionLabel="Unknown"/>
</h:selectOneMenu>    
<a4j:outputPanel id="detectorSubType">
    <h:selectOneMenu value="#{detectorInstance.detectorSubType}" converter="detectorSubTypeConverter"/>
</a4j:outputPanel>    

DetectorSubTypeConverter.java

@Name("detectorSubTypeConverter")
@BypassInterceptors
@org.jboss.seam.annotations.faces.Converter
public class DetectorSubTypeConverter implements Converter {
    public Object getAsObject(final FacesContext facesContext, final UIComponent uiComponent, final String identifier) {
        return identifier;
    }

    public String getAsString(final FacesContext facesContext, final UIComponent uiComponent, final Object o) {
        return o.toString();
    }
}

探测器.js

function updateSubTypes(typeSelect, appName) {
    var jsonRoot = appName + "/services/rest/detectors/detectors";

    jQuery.getJSON(jsonRoot, function(data) {
        var subTypes = getSubTypes(typeSelect, data);
        var subTypeSelect = typeSelect.next().firstChild;
        subTypeSelect.options.length = 0;
        for (var i = 0; i < subTypes.length; i++) {
            subTypeSelect.options[i] = new Option(subTypes[i], subTypes[i], false, false);
        }
    });
}

function getSubTypes(typeSelect, detectors) {
    var selection = typeSelect.options[typeSelect.selectedIndex].text;
    var subtypes = new Array();
    for (var i = 0; i < detectors.length; i++) {
        var uuid = detectors[i]['detector']['name'];
        if (selection == uuid) {
            for (var j = 0; j < detectors[i]['detector']['subtypes'].length; j++) {
                subtypes[j] = detectors[i]['detector']['subtypes'][j]['name'];
            }
        }
    }

    return subtypes;
}
4

1 回答 1

0

我不认为通过 JS 为 selectOneMenu 填充项目是使用 Seam/JSF 的正确方法。原因是当您显示带有项目列表的下拉列表时,Seam/JSF 将出于安全原因检查提交的值是否在列表中。

正确的方法是:

  • 处理第一个下拉列表的 onchange 事件并重新计算服务器上第二个下拉列表的项目
  • 然后重新渲染第二个下拉列表

思路如下:

<h:selectOneMenu value="#{detectorInstance.type}" converter="detectorConverter" onchange="updateSubTypes(this, '#{applicationName}')">
    <s:selectItems value="#{detectors.detectors}" var="detectorSelection" label="#{detectorSelection.name}" noSelectionLabel="Unknown"/>
    <a4j:ajax event="click" execute="@this" render="detectorSubType" 
        listener="#{detectorInstance.onTypeChange}"/>
</h:selectOneMenu>
<a4j:outputPanel id="detectorSubType">
    <h:selectOneMenu value="#{detectorInstance.detectorSubType}" converter="detectorSubTypeConverter">
        <f:selectItem value="#{detectorInstance.types}" />
    </h:selectOneMenu>
</a4j:outputPanel>

第二个下拉列表的项目来自detectorInstance.types。在detectorInstance.onTypeChange中,您重新计算detectorInstance.types然后重新渲染它render="detectorSubType"

于 2013-12-12T04:28:44.263 回答