1

デフォルトでは、プライム フェースのコマンド ボタンは子コンポーネントをレンダリングしません。これを実現するために、カスタム レンダラーを実装しました。動作しますが、子コンポーネントが 2 回レンダリングされていることがわかりました。レンダリングされたボタンの内側に 1 回、ボタンのすぐ外側に 1 回。カスタム レンダラーが子コンポーネントを 1 回しか書き込んでいないことを確認しました。

カスタムレンダラーは次のとおりです。

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 を次に示します (Web ページでソースを表示)。

<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>

ここに画像の説明を入力

ご覧のとおり、p:commandButton の子コンポーネントは、私のレンダラーは 1 回しか出力していませんが、2 回出力されています。commandButton は通常、子コンポーネントを出力しないという事実と関係があると思われます。

このエラーを解決するために何をする必要があるか知っている人はいますか?

ありがとう。

4

0 に答える 0