简体   繁体   English

我如何在将Collection绑定到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?

This is a follow-up to: How can I create a JSF composite component that binds a Collection to both an h:selectOneMenu and h:selectManyListbox? 这是后续操作: 如何创建将Collection绑定到h:selectOneMenu和h:selectManyListbox的JSF复合组件?

I have a composite component that allows a user to toggle between ah:selectOneMenu and h:selectManyListbox and returns a Collection as the "selected" value. 我有一个复合组件,允许用户在ah:selectOneMenu和h:selectManyListbox之间切换,并返回Collection作为“ selected”值。 This works great. 这很好。 I'm now attempting to add ajax support to it so that, if a value is selected in the menu or listbox, an ajax event is fired (meaning mySelected should have its value populated and I can re-render any other component on the page I want. 我现在正尝试向其添加ajax支持,以便如果在菜单或列表框中选择了某个值,则会引发ajax事件(这意味着mySelected应该填充其值,并且我可以重新呈现页面上的任何其他组件我想要。

<swr:singleMultiSelect list="#{myBean.myList}"
                       selected="#{myBean.mySelected}"
                       singleSelect="#{myBean.singleSelect}">
    <f:ajax event="valueChange" execute="@this" 
            render="buttonPanel"/>
</swr:singleMultiSelect>

With the following attribute in my composite component: 在我的复合组件中具有以下属性:

<cc:clientBehavior name="valueChange" event="valueChange"
                   targets="selectOneMenu selectManyListbox"/>

I'm having problems populating mySelected with the value of the selectOneMenu. 我在用selectOneMenu的值填充mySelected时遇到问题。 When I do a non-ajax form submit, processUpdates takes care of this...I'm not quite sure how to have it do the same thing for ajax event though. 当我执行非ajax表单提交时, processUpdates会处理此问题……我不太确定如何让它对ajax事件执行相同的操作。

Here is my composite component code: 这是我的复合组件代码:

singleMultiSelect.xhtml 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 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;
    }
}

Added an ajax tag to the selectOneMenu with a listener (bound to a method in the FacesComponent) which updates the selected Collection: 使用一个侦听器(绑定到FacesComponent中的方法)将一个ajax标记添加到selectOneMenu,该侦听器将更新选定的Collection:

singleMultiSelect.xhtml: 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: 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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM