我有一个目前不易实施的要求。应根据
SelectOneMenu
选择在此处预先选择自动完成功能。为此,我需要之前在 completeMethod
中选择的值。
一般来说,从completeMethod返回的列表应该按所选值进行过滤。
我尝试使用
f:attribute
解决问题。不幸的是,这里的值始终为 null,因为我使用的是请求范围的 bean。
这是我当前尝试的代码:
查看:
<h:form id="myForm">
<h:outputLabel value="My Selection" for="selectFldId" />
<p:selectOneMenu
value="#{autocompleteWithPreSelectionBean.selectedValue}"
id="selectFldId">
<f:selectItem itemLabel="Select One" itemValue=""
noSelectionOption="true" />
<f:selectItems
value="#{autocompleteWithPreSelectionBean.selectItems}" />
<p:ajax event="change" update="autoCompleteId" process="@this" />
</p:selectOneMenu>
<p:autoComplete
disabled="#{empty autocompleteWithPreSelectionBean.selectedValue}"
value="#{autocompleteWithPreSelectionBean.completedText}"
id="autoCompleteId"
completeMethod="#{autocompleteWithPreSelectionBean.completeText}">
<f:attribute name="filter"
value="#{autocompleteWithPreSelectionBean.selectedValue}" />
</p:autoComplete>
</h:form>
豆:
@Named(value = "autocompleteWithPreSelectionBean")
@RequestScoped
public class AutocompleteWithPreSelectionBean implements Serializable {
private List<SelectItem> selectItems;
private String selectedValue;
private String completedText;
@PostConstruct
public void init() {
selectItems = new ArrayList<>();
selectItems.add(new SelectItem("ID1", "Value 1"));
selectItems.add(new SelectItem("ID2", "Value 2"));
selectItems.add(new SelectItem("ID3", "Value 3"));
selectItems.add(new SelectItem("ID4", "Value 4"));
selectItems.add(new SelectItem("ID5", "Value 5"));
}
public List<String> completeText(String query) {
String filterValue = (String) UIComponent.getCurrentComponent(FacesContext.getCurrentInstance()).getAttributes()
.get("filter");
//selectedValue is null
//filterValue is null
...
}
...
}
是否有一个解决方案可以满足我的要求,让我可以继续使用请求范围的 bean?也欢迎其他方法或解决方案。
我正在使用 Faces 4 和 PrimeFaces 13。
有两个因素导致了可观察到的问题。
disabled
属性也会在“应用请求值”阶段进行评估。
<p:autoComplete ... disabled="#{empty autocompleteWithPreSelectionBean.selectedValue}">
但是,在请求作用域 bean 的情况下,这将always 评估
true
,因为 selectedValue
已被清除,并且仅在更新模型值阶段设置。这是“应用请求值”阶段“之后”。因此,这永远无法评估 false
,因此自动完成组件在应用请求值阶段基本上永久禁用。解决此问题的一种方法是让它检查与下拉组件关联的请求参数,而不是与下拉组件关联的模型值。
<p:selectOneMenu ... binding="#{selectFld}" />
<p:autoComplete ... disabled="#{empty param[selectFld.clientId += '_input']}" />
如果您使用 PrimeFacesPartial Submit
功能,那么只有当您将以下 <p:ajax>
添加到自动完成组件时才会起作用,该组件明确指示 ajax 也发送下拉组件的提交值:
<p:autoComplete ...>
<p:ajax event="query" process="@this selectFldId" update="@this" />
</p:autoComplete>
其次,为了让与下拉组件关联的 bean 属性已经在自动完成方法中预先填充,我希望前面演示的
<p:ajax>
足以完成任务:
public List<String> completeText(String query) {
System.out.println(selectedValue); // Should already be populated.
// ...
}
然而,我惊讶地发现这仍然是
null
。然后我进行了一些调试,更惊讶地发现完整的方法是在“应用请求值”阶段而不是预期的“调用应用程序”阶段调用的!我不确定这是不是故意的。
所以我们能做的最好的事情就是继续<f:attribute>
技巧,但这次重用
disabled
属性中使用的请求参数映射技巧:<p:autoComplete ...>
<f:attribute name="filter" value="#{param[selectFld.clientId += '_input']}" />
</p:autoComplete>
public List<String> completeText(String query) {
String filterValue = (String) UIComponent.getCurrentComponent(FacesContext.getCurrentInstance()).getAttributes().get("filter");
// ...
}
,这里没有正确理解noSelectionOption="true"
。在你的上下文中它基本上被完全忽略了。请改用
itemValue="#{null}"
。另请参阅 在 JSF 中向 selectOneMenu 添加“未选择任何内容”选项的最佳方法。