默认情况下,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">×</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(在网页上查看源代码):
<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 的子组件被打印了两次,尽管我的渲染器只打印了一次。我怀疑这与 commandButton 通常不打印子组件有关。
有谁知道我需要做什么来解决这个错误?
谢谢。