繁体   English   中英

如何在EL内部测试JSF复合组件是否与f:ajax标签一起使用?

[英]How can I test, inside EL, if a JSF composite component is used with an f:ajax tag?

我的复合组件使用clientBehavior标记对f:ajax标记具有可选支持:

singleMultiSelect.xhtml

<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}"/>

                <!-- THIS PART IS NOT WORKING BECAUSE IT RETURNS 0
                     NO MATTER IF F:AJAX IS USED OR NOT -->
                <c:if test="#{cc.getClientBehaviors().size() > 0}">
                    <f:ajax event="valueChange" execute="@this"
                            listener="#{cc.updateSelected}"/>
                </c:if>
            </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);
    }

    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);
        }
    }

    /**
     * @return the singleSelected
     */
    public UISelectOne getSingleSelected() {
        return singleSelected;
    }

    /**
     * @param singleSelected the singleSelected to set
     */
    public void setSingleSelected(UISelectOne singleSelected) {
        this.singleSelected = singleSelected;
    }
}

我如何在EL内测试客户端实际上是否使用ajax。 例如:

<mylib:mycomp />

VS

<mylib:mycomp>
    <f:ajax event="valueChange"/>
</mylib:mycomp>

在代码中,您可以看到我尝试使用cc.getClientBehaviors()。size()来查看是否存在客户端行为,但该行为始终返回0。

您可以在内部复合组件代码中检查这些属性,例如。

1)如果插入了特定行为

#{empty cc.getClientBehaviors().get("valueChange")}

2)或任何

#{cc.getClientBehaviors().size() > 0}

JSF组件必须实现ClientBehaviorHolder接口,并且必须重写getEventNames()方法以返回受支持事件的列表:

SingleMultiSelect.java:

public class SingleMultiSelect extends UINamingContainer implements ClientBehaviorHolder {

    ...

    @Override
    public Collection<String> getEventNames() {
        Collection<String> eventNames = new HashSet<>();
        eventNames.add("valueChange");
        return eventNames;
    }

    ...
}

一旦完成,@ rvillar的答案就起作用了:

1)如果插入了特定行为

#{empty cc.getClientBehaviors().get("valueChange")}

2)或任何

#{cc.getClientBehaviors().size() > 0}

暂无
暂无

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

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