如何向将集合绑定到 h:selectOneMenu 和 h:selectManyListbox 的复合组件添加 f:ajax 支持?
How can I add f:ajax support to my composite component that binds a Collection to an h:selectOneMenu and h:selectManyListbox?
这是以下内容的后续:
我有一个复合组件,允许用户在 h:selectOneMenu 和 h:selectManyListbox 和 returns 集合之间切换作为 "selected" 值。这很好用。我现在正在尝试向它添加 ajax 支持,这样,如果在菜单或列表框中选择了一个值,就会触发 ajax 事件(意思是 mySelected 应该填充它的值,我可以在我想要的页面上重新呈现任何其他组件。
<swr:singleMultiSelect list="#{myBean.myList}"
selected="#{myBean.mySelected}"
singleSelect="#{myBean.singleSelect}">
<f:ajax event="valueChange" execute="@this"
render="buttonPanel"/>
</swr:singleMultiSelect>
在我的复合组件中具有以下属性:
<cc:clientBehavior name="valueChange" event="valueChange"
targets="selectOneMenu selectManyListbox"/>
我在使用 selectOneMenu 的值填充 mySelected 时遇到问题。当我提交非 ajax 表单时,processUpdates 会处理这个...我不太确定如何让它为 [=43 做同样的事情=] 事件虽然。
这是我的复合组件代码:
singleMultiSelect.xhtml
<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE html>
<ui:composition
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
>
<cc:interface componentType="singleMultiSelect">
<!-- The initial list of objects -->
<cc:attribute name="list" type="java.util.List" required="true"/>
<!-- The selected objects -->
<cc:attribute name="selected" type="java.util.Collection" required="true"/>
<!-- whether to display the selectOneMenu (true) or selectManyBox (false) -->
<cc:attribute name="singleSelect" type="java.lang.Boolean"
required="false" default="true"/>
<cc:clientBehavior name="valueChange" event="valueChange"
targets="selectOneMenu selectManyListbox"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}">
<ace:checkboxButton id="singleSelectChkBx"
value="#{cc.attrs.singleSelect}">
<ace:ajax render="#{cc.clientId}"/>
</ace:checkboxButton>
<h:selectOneMenu id="selectOneMenu"
rendered="#{cc.attrs.singleSelect}"
binding="#{cc.singleSelected}">
<f:selectItems value="#{cc.attrs.list}"/>
</h:selectOneMenu>
<h:selectManyListbox id="selectManyListbox"
rendered="#{! cc.attrs.singleSelect}"
value="#{cc.attrs.selected}">
<f:selectItems value="#{cc.attrs.list}"/>
</h:selectManyListbox>
</span>
</cc:implementation>
</ui:composition>
SingleMultiSelect.java
public class SingleMultiSelect extends UINamingContainer {
private UISelectOne singleSelected;
public SingleMultiSelect() {
super();
}
@Override
public void processUpdates(FacesContext context) {
super.processUpdates(context);
if (getAttributes().get("singleSelect") == Boolean.TRUE) {
HashSet selected = new HashSet();
if(singleSelected.getValue() != null) {
selected.add(singleSelected.getValue());
}
getValueExpression("selected").setValue(context.getELContext(), selected);
}
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
if (getAttributes().get("singleSelect") == Boolean.TRUE) {
Collection selected = (Collection) getAttributes().get("selected");
if (selected != null && !selected.isEmpty()) {
singleSelected.setValue(selected.iterator().next());
} else {
singleSelected.setValue(null);
}
}
super.encodeBegin(context);
}
/**
* @return the singleSelected
*/
public UISelectOne getSingleSelected() {
return singleSelected;
}
/**
* @param singleSelected the singleSelected to set
*/
public void setSingleSelected(UISelectOne singleSelected) {
this.singleSelected = singleSelected;
}
}
向带有侦听器(绑定到 FacesComponent 中的方法)的 selectOneMenu 添加了一个 ajax 标记,它会更新选定的集合:
singleMultiSelect.xhtml:
<h:selectOneMenu id="selectOneMenu"
rendered="#{cc.attrs.singleSelect}"
binding="#{cc.singleSelected}">
<f:selectItems value="#{cc.attrs.list}"/>
<f:ajax event="valueChange" execute="@this"
listener="#{cc.updateSelected}"/>
</h:selectOneMenu>
SingleMultiSelect.java:
public void updateSelected(AjaxBehaviorEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
if (getAttributes().get("singleSelect") == Boolean.TRUE) {
HashSet selected = new HashSet();
if(singleSelected.getValue() != null) {
selected.add(singleSelected.getValue());
}
getValueExpression("selected").setValue(context.getELContext(), selected);
}
}
这是以下内容的后续:
我有一个复合组件,允许用户在 h:selectOneMenu 和 h:selectManyListbox 和 returns 集合之间切换作为 "selected" 值。这很好用。我现在正在尝试向它添加 ajax 支持,这样,如果在菜单或列表框中选择了一个值,就会触发 ajax 事件(意思是 mySelected 应该填充它的值,我可以在我想要的页面上重新呈现任何其他组件。
<swr:singleMultiSelect list="#{myBean.myList}"
selected="#{myBean.mySelected}"
singleSelect="#{myBean.singleSelect}">
<f:ajax event="valueChange" execute="@this"
render="buttonPanel"/>
</swr:singleMultiSelect>
在我的复合组件中具有以下属性:
<cc:clientBehavior name="valueChange" event="valueChange"
targets="selectOneMenu selectManyListbox"/>
我在使用 selectOneMenu 的值填充 mySelected 时遇到问题。当我提交非 ajax 表单时,processUpdates 会处理这个...我不太确定如何让它为 [=43 做同样的事情=] 事件虽然。
这是我的复合组件代码:
singleMultiSelect.xhtml
<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE html>
<ui:composition
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
>
<cc:interface componentType="singleMultiSelect">
<!-- The initial list of objects -->
<cc:attribute name="list" type="java.util.List" required="true"/>
<!-- The selected objects -->
<cc:attribute name="selected" type="java.util.Collection" required="true"/>
<!-- whether to display the selectOneMenu (true) or selectManyBox (false) -->
<cc:attribute name="singleSelect" type="java.lang.Boolean"
required="false" default="true"/>
<cc:clientBehavior name="valueChange" event="valueChange"
targets="selectOneMenu selectManyListbox"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}">
<ace:checkboxButton id="singleSelectChkBx"
value="#{cc.attrs.singleSelect}">
<ace:ajax render="#{cc.clientId}"/>
</ace:checkboxButton>
<h:selectOneMenu id="selectOneMenu"
rendered="#{cc.attrs.singleSelect}"
binding="#{cc.singleSelected}">
<f:selectItems value="#{cc.attrs.list}"/>
</h:selectOneMenu>
<h:selectManyListbox id="selectManyListbox"
rendered="#{! cc.attrs.singleSelect}"
value="#{cc.attrs.selected}">
<f:selectItems value="#{cc.attrs.list}"/>
</h:selectManyListbox>
</span>
</cc:implementation>
</ui:composition>
SingleMultiSelect.java
public class SingleMultiSelect extends UINamingContainer {
private UISelectOne singleSelected;
public SingleMultiSelect() {
super();
}
@Override
public void processUpdates(FacesContext context) {
super.processUpdates(context);
if (getAttributes().get("singleSelect") == Boolean.TRUE) {
HashSet selected = new HashSet();
if(singleSelected.getValue() != null) {
selected.add(singleSelected.getValue());
}
getValueExpression("selected").setValue(context.getELContext(), selected);
}
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
if (getAttributes().get("singleSelect") == Boolean.TRUE) {
Collection selected = (Collection) getAttributes().get("selected");
if (selected != null && !selected.isEmpty()) {
singleSelected.setValue(selected.iterator().next());
} else {
singleSelected.setValue(null);
}
}
super.encodeBegin(context);
}
/**
* @return the singleSelected
*/
public UISelectOne getSingleSelected() {
return singleSelected;
}
/**
* @param singleSelected the singleSelected to set
*/
public void setSingleSelected(UISelectOne singleSelected) {
this.singleSelected = singleSelected;
}
}
向带有侦听器(绑定到 FacesComponent 中的方法)的 selectOneMenu 添加了一个 ajax 标记,它会更新选定的集合:
singleMultiSelect.xhtml:
<h:selectOneMenu id="selectOneMenu"
rendered="#{cc.attrs.singleSelect}"
binding="#{cc.singleSelected}">
<f:selectItems value="#{cc.attrs.list}"/>
<f:ajax event="valueChange" execute="@this"
listener="#{cc.updateSelected}"/>
</h:selectOneMenu>
SingleMultiSelect.java:
public void updateSelected(AjaxBehaviorEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
if (getAttributes().get("singleSelect") == Boolean.TRUE) {
HashSet selected = new HashSet();
if(singleSelected.getValue() != null) {
selected.add(singleSelected.getValue());
}
getValueExpression("selected").setValue(context.getELContext(), selected);
}
}