如何通过JavaScript触发h:inputHidden的更改

时间:2013-11-15 18:34:39

标签: ajax jsf-2 composite-component

我必须将三态复选框实现为具有ajax功能的复合组件。 这就是我到目前为止所做的:

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:cc="http://java.sun.com/jsf/composite"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich">

    <cc:interface>
        <cc:attribute name="id" /><!-- necessary? -->
        <cc:attribute name="value" required="false" />
        <cc:clientBehavior name="change" event="change" targets="value" />
    </cc:interface>
    <cc:implementation>
        <div style="float: left;">
            <h:outputStylesheet library="default" name="css/checkbox.css" target="head" />
            <h:outputScript library="default" name="js/checkbox.js" target="head" />

            <div id="#{cc.clientId}" class="cc-checkbox cc-checkbox-value#{cc.attrs.value}"
                style="width: 14px; height: 14px;" onclick="checkboxToggleControl('#{cc.clientId}')"></div>
            <h:inputHidden id="value" value="#{cc.attrs.value}" />
        </div>
    </cc:implementation>
</ui:composition>

如您所见(或不是,因为我没有包含JS,因为它不是问题),一个小型JavaScript将用户看到的类替换为三态复选框(null,{{1 },true)。当前值由JavaScript存储在false中。

我希望能够在使用控件时注册ajax事件,以便能够将值存储在服务器上。该组件位于<h:inputHidden>内。每次用户点击它时,该值应“立即”存储在数据库中。将<rich:extendedDataTable>clientBehaviour一起使用不起作用,因为它不支持ajax。

  1. 是否可以使用inputHidden来解析<h:inputHidden>?有什么缺点? (我不得不处理验证,不是吗?)

  2. 有没有其他方法可以将其作为复合组件实现?

  3. 或者,编写“真实”组件会“更容易”吗?

  4. 我没有使用<h:inputText>,因为CSS无法以所需方式设置样式,也因为它不支持三态。

1 个答案:

答案 0 :(得分:4)

确实,<f:ajax change>不支持<h:inputHidden>。您只会得到以下异常,因为组件后面的HtmlInputHidden class未实现ClientBehaviorHolder interface

  

javax.faces.view.facelets.TagException: /test.xhtml @23,52 <f:ajax> Unable to attach <f:ajax> to non-ClientBehaviorHolder parent

您确实需要用<h:inputText>替换它。您可以使用CSS display:none;隐藏它。您只需要意识到通过JavaScript操纵其值不会自动触发任何HTML DOM事件。您需要通过在HTML DOM元素上显式调用change来手动触发onchange()事件:

var input = document.getElementById(...);
input.value = newValue;
input.onchange();

或者,如果你碰巧总体上使用jQuery,

var $input = $("#...");
$input.val(newValue);
$input.change(); // Or $input.trigger("change");

无关具体问题,关于此处评论中的问题:

<cc:attribute name="id" /><!-- necessary? -->

仅用于纪录片目的。即当你真正使用shortDescription时。

<cc:attribute name="id" shortDescription="The ID of the composite." />

但是否则它已经从UIComponent基类继承(如bindingrendered)。