使用JS填充的selectOneMenu在JSF和Seam中设置String

时间:2013-04-23 19:54:49

标签: jsf seam

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

Edit.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();
    }
}

detectors.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;
}

1 个答案:

答案 0 :(得分: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"重新呈现