当属性可编辑为真时,SelectOneMenu传递itemLabel而不是itemValue

时间:2017-08-11 07:22:26

标签: java jsf primefaces jsf-2.2 selectonemenu

我有以下选择一个菜单。我有一个转换器用于我的" Intezet" (机构)对象。

<p:selectOneMenu id="bekuldo" filter="true" filterMatchMode="contains" required="true" converter="intezetConverter" disabled="#{iratFelvitelView.disabled}" value="#{iratFelvitelView.bekuldo}" placeholder="Válaszd ki vagy add meg!" editable="true">

  <f:selectItem noSelectionOption="true" itemLabel="Válassz egyet:" itemValue="#{null}" itemDisabled="#{iratFelvitelView.bekuldo ne null}" />
  <f:selectItems value="#{dataFromDBean.intezetek}" var="intezet" itemLabel="#{intezet.name}" itemValue="#{intezet}" />
</p:selectOneMenu>
@FacesConverter(value = "intezetConverter")
public class IntezetConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext ctx, UIComponent uiComponent, String id) {
        ValueExpression vex = ctx.getApplication().getExpressionFactory().createValueExpression(ctx.getELContext(),
                "#{dataFromDBean}", DataFromDBean.class);

        DataFromDBean objects = (DataFromDBean) vex.getValue(ctx.getELContext());
        Intezet object = null;
        try {
            UUID guid = UUID.fromString(id);
            object = objects.getIntezet(guid);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            object = new Intezet(id);
        }

        return object;
    }

    @Override
    public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object obj) {
        if (obj == null)
            return "";
        if (obj.getClass().equals(String.class)) {
            return (String) obj;
        }
        return ((Intezet) obj).getId().toString();
    }

}

getAsObject中调用的构造函数是:

public Intezet(String name) {
        super();
        this.id = UUID.randomUUID();
        this.name = name;
        this.passziv = false;
    }

基本上我的逻辑是selectOneMenu使用现有对象作为值,用户可以选择,并且还添加新值,即String,如果传递了String,则不会有id发现,所以字符串作为id传递,然后如果一个id不能被解析为UUID,那么它不是一个UUID字符串,所以创建一个新对象,由服务器保存提交表格。

然而,问题是,当editable="true"存在时,selectOneMenu总是将String传递给转换器,但不只是String,而是itemLabel {1}}值,即机构的名称表示。即使是noselectoption也是以它的itemLabel而不是#{null}传递的。 因此,无论用户输入新值还是选择现有值,始终将itemLabel属性传递给转换器,因此我的转换器将其视为新值并尝试创建新的Institution。这是JSFPrimeFaces中的已知错误吗?

根据Usagi Miyamoto的建议,<p:autoComplete>是我的问题的解决方法。

以下代码按照我最初的需要(就功能而言)起作用:

<p:autoComplete id="bekuldo" value="#{iratFelvitelView.bekuldo}" completeMethod="#{iratFelvitelView.completeIntezet}"
                    var="intezet" itemLabel="#{intezet.name}" itemValue="#{intezet}" converter="intezetConverter" dropdown="true" disabled="#{iratFelvitelView.disabled}"/>

使用以下完整方法:

public Collection<Intezet> completeIntezet(String query) {
    Collection<Intezet> filteredIntezet = new ArrayList<>();
    for (Intezet intezet : intezetek) {
        if (intezet.getName().toLowerCase().contains(query.toLowerCase().trim())) {
            filteredIntezet.add(intezet);
        }
    }
    return filteredIntezet;
}

1 个答案:

答案 0 :(得分:0)

它是RichFaces 3.x,所以JSF 1.x,但类似的内容也适用于JSF 2.xPrimeFaces

XHTML:

<a4j:region>
  <h:inputText id="person" value="#{bean.item.id}">
    <a4j:support event="onblur" action="#{bean.listener}" reRender="partner" />
  </h:inputText>
  <rich:suggestionbox id="partnerSuggest" for="partner" var="part" fetchValue="#{part.id}"
                      suggestionAction="#{bean.suggest}" reRender="partner">
    <rich:column><h:outputText value="#{part.id}"/></rich:column>
    <rich:column><h:outputText value="#{part.name}"/></rich:column>
    <a4j:support event="onselect" action="#{bean.listener}" reRender="partner" />
  </rich:suggestionBox>
</a4j:region>

Bean.java:

public class Bean
{
  // Currently selected/edited Person
  private Person item = new Person();

  // Getters and Setters omitted...

  // This method is invoked to present a list fro the <rich:suggestionbox> component.
  // It receives the typed in text as parameter.
  public List<Partner> suggest( Object value )
  {
    // Returns a list of partner filtered by the given value.
    // In my case it could be a name or an ID...
  }

  // This method (an action) is called when the input field is lost focus (onblur event) or
  // a selection is made from the suggestion list.
  // It checks wheter the input field contains a valid ID, and sets the bean to the correct
  // partner it loaded.
  public String listener()
  {
    String value = this.item.getId();
    final Partner who = Partner.find( value ); // To retrieve the partner
    if ( null != who )
    {
        this.item = who;
    }
    return null;
  }
}