デフォルトでは、プライム フェースのコマンド ボタンは子コンポーネントをレンダリングしません。これを実現するために、カスタム レンダラーを実装しました。動作しますが、子コンポーネントが 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">×</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="<i class="icon-spinner ast-alt icon-spin"></i> #{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 は通常、子コンポーネントを出力しないという事実と関係があると思われます。
このエラーを解決するために何をする必要があるか知っている人はいますか?
ありがとう。