[英]SelectOneMenu passes itemLabel instead of itemValue when attribute editable is true
I have the following select one menu.我有以下选择一个菜单。 And I have a converter for my "Foo" object.
我有一个用于“Foo”对象的转换器。
<p:selectOneMenu id="sender" filter="true" filterMatchMode="contains" required="true" converter="fooConverter" disabled="#{myView.disabled}" value="#{myView.sender}" placeholder="Pick one or create new!" editable="true">
<f:selectItem noSelectionOption="true" itemLabel="Pick one:" itemValue="#{null}" itemDisabled="#{myView.sender ne null}" />
<f:selectItems value="#{dataFromDBean.foos}" var="foo" itemLabel="#{foo.name}" itemValue="#{foo}" />
</p:selectOneMenu>
@FacesConverter(value = "fooConverter")
public class FooConverter 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());
Foo object = null;
try {
UUID guid = UUID.fromString(id);
object = objects.getFoo(guid);
} catch (IllegalArgumentException e) {
e.printStackTrace();
object = new Foo(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 ((Foo) obj).getId().toString();
}
}
And the constructor called in getAsObject
is:在
getAsObject
调用的构造函数是:
public Foo(String name) {
super();
this.id = UUID.randomUUID();
this.name = name;
this.passive = false;
}
Basically my logic is that the selectOneMenu
uses the existing objects as values, which the user can select, and also add new value, which is a String, and if a String is passed, than no id will be found, so the string is passed as id instead, and then if an id can't be parsed into a UUID, then it is not a UUID string, so a new object is created, which will be saved by the server on submitting the form.基本上我的逻辑是
selectOneMenu
使用现有对象作为值,用户可以选择这些值,并添加新值,它是一个字符串,如果传递一个字符串,则不会找到 id,因此传递字符串改为 id,然后如果 id 无法解析为 UUID,则它不是 UUID 字符串,因此会创建一个新对象,该对象将在提交表单时由服务器保存。
However, the problem is, that when editable="true"
is present, the selectOneMenu
always passes a String
to the converter, but not just any String
, but the itemLabel
value, which is the name representation of the Institution.然而,问题是,当
editable="true"
存在时, selectOneMenu
总是将String
传递给转换器,但不仅仅是任何String
,而是itemLabel
值,它是机构的名称表示。 Even the noselectoption is passed as it's itemLabel and never #{null}
.甚至 noselectoption 也作为 itemLabel 传递,而不是
#{null}
。 So regardless if the user enters a new value, or selects an existing one, always the itemLabel
attribute is passed to the converter, so my converter sees it as a new value and tries to create the new Institution.因此,无论用户输入新值还是选择现有值,
itemLabel
属性始终传递给转换器,因此我的转换器将其视为新值并尝试创建新机构。 Is this a known bug in JSF
or PrimeFaces
?这是
JSF
或PrimeFaces
的已知错误吗?
As suggested by Usagi Miyamoto, <p:autoComplete>
is a workaround to my issue.正如 Usagi Miyamoto 所建议的,
<p:autoComplete>
是我的问题的一种解决方法。
The following code works as I originally wanted it (in terms of functionality):以下代码按我原先想要的方式工作(在功能方面):
<p:autoComplete id="sender" value="#{myView.sender}" completeMethod="#{myView.completeFoo}"
var="foo" itemLabel="#{foo.name}" itemValue="#{foo}" converter="fooConverter" dropdown="true" disabled="#{myView.disabled}"/>
With the following complete method:使用以下完整方法:
public Collection<Foo> completeFoo(String query) {
Collection<Foo> filteredFoo = new ArrayList<>();
for (Foo foo : foos) {
if (foo.getName().toLowerCase().contains(query.toLowerCase().trim())) {
filteredFoo.add(foo);
}
}
return filteredFoo;
}
It is RichFaces 3.x
, so JSF 1.x
, but something similar should work in JSF 2.x
with PrimeFaces
, too.它是
RichFaces 3.x
,所以是JSF 1.x
,但类似的东西也应该在带有PrimeFaces
JSF 2.x
工作。
XHTML: 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:豆.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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.