使用自定义渲染器进行primefaces commandButton时,子组件呈现两次

时间:2013-02-11 19:54:36

标签: jsf jsf-2 primefaces

默认情况下,prime faces命令按钮不会呈现子组件。我已经实现了一个自定义渲染器来实现这一目标。然而,它有效,我发现子组件被渲染两次;一旦进入渲染按钮,一旦进入按钮之外​​,紧接在它之前。我已经确认我的自定义渲染器只编写子组件一次。

这是自定义渲染器:

public class ApsCommandButtonRenderer extends CommandButtonRenderer {

    @Override
    protected void encodeMarkup(FacesContext context, CommandButton button) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String clientId = button.getClientId(context);
        String type = button.getType();
        String value = (String) button.getValue();
        String icon = button.resolveIcon();

        StringBuilder onclick = new StringBuilder();
        if(button.getOnclick() != null) {
            onclick.append(button.getOnclick()).append(";");
        }

        writer.startElement("button", button);
        writer.writeAttribute("id", clientId, "id");
        writer.writeAttribute("name", clientId, "name");

        String style = button.getStyleClass();

        if (!StringUtils.isBlank(style)) {
            writer.writeAttribute("class", style, "styleClass");
        }

        if(!type.equals("reset") && !type.equals("button")) {
            String request;

            if(button.isAjax()) {
                request = buildAjaxRequest(context, button, null);
            }
            else {
                UIComponent form = ComponentUtils.findParentForm(context, button);
                if(form == null) {
                    throw new FacesException("CommandButton : \"" + clientId + "\" must be inside a form element");
                }

                request = buildNonAjaxRequest(context, button, form, null, false);
            }

            onclick.append(request);
        }

        String onclickBehaviors = getOnclickBehaviors(context, button);
        if(onclickBehaviors != null) {
            onclick.append(onclickBehaviors).append(";");
        }

        if(onclick.length() > 0) {
            writer.writeAttribute("onclick", onclick.toString(), "onclick");
        }

        renderPassThruAttributes(context, button, HTML.BUTTON_ATTRS, HTML.CLICK_EVENT);

        if(button.isDisabled()) writer.writeAttribute("disabled", "disabled", "disabled");
        if(button.isReadonly()) writer.writeAttribute("readonly", "readonly", "readonly");

        //icon
        if(icon != null) {
            String defaultIconClass = button.getIconPos().equals("left") ? HTML.BUTTON_LEFT_ICON_CLASS : HTML.BUTTON_RIGHT_ICON_CLASS;
            String iconClass = defaultIconClass + " " + icon;

            writer.startElement("span", null);
            writer.writeAttribute("class", iconClass, null);
            writer.endElement("span");
        }

        //text
        //writer.startElement("span", null);
        //writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);

        if(value != null) {
            if(button.isEscape())
                writer.writeText(value, "value");
            else
                writer.write(value);
        }

        renderChildren(context, button);

        //writer.endElement("span");

        writer.endElement("button");
    }

这是xhtml页面上的标记:

            <h:form styleClass="form-signin" id="login-form" method="POST">

                <h:graphicImage library="images" name="watchopolis/logo-cs.png"/>

                <h2 class="form-signin-heading">#{msgs['login.prompt']} <span>#{msgs['login.register.prompt']} <a
                        href="register.htm">#{msgs['click.here']}</a></span></h2>

                <h:panelGrid rendered="#{param.logout != null}" style="width: 100%">
                    <div class="alert alert-success">
                        <button type="button" class="close" data-dismiss="alert">&times;</button>
                        #{msgs['logout.success']}
                    </div>
                </h:panelGrid>

                <fieldset>
                    <h:inputText id="username" value="#{loginBean.username}" styleClass="input-block-level" required="true" requiredMessage="#{msgs['login.username.missing']}" />
                    <p:watermark value="#{msgs['email.address']}" for="username" />

                    <h:inputSecret id="password" value="#{loginBean.password}" styleClass="input-block-level" required="true" requiredMessage="#{msgs['login.password.missing']}" />
                    <p:watermark value="#{msgs['password']}" for="password" />

                    <p:commandButton action="authenticate" id="login-button" styleClass="btn btn-medium btn-primary" type="submit" value="&lt;i class=&quot;icon-spinner ast-alt icon-spin&quot;&gt;&lt;/i&gt; #{msgs['login']}" escape="false" />
                </fieldset>
            </h:form>

最后,这是生成的HTML(网页上的查看源代码):

<i class="icon-spinner ast-alt icon-spin"></i> Login

    <button id="login-form:login-button" name="login-form:login-button" class="btn btn-medium btn-primary" onclick="PrimeFaces.ab({source:'login-form:login-button'});return false;" type="submit">
        <i class="icon-spinner ast-alt icon-spin"></i> Login
    </button>

enter image description here

如您所见,p:commandButton的子组件打印两次,即使我的渲染器只打印一次。我怀疑它与commandButton通常不打印子组件这一事实有关。

有谁知道我需要做些什么才能解决此错误?

感谢。

0 个答案:

没有答案