これは、の状態を表すチェックボックス<p:selectBooleanButton>
が実際にPrimeFacesによってレンダリングされた方法によるものSelectBooleanButtonRenderer
です。
<div id="formId:buttonId" type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only">
<input id="formId:buttonId_input" name="formId:buttonId_input" type="checkbox" class="ui-helper-hidden">
<span class="ui-button-text">no</span>
</div>
チェックボックスはクラスのCSSdisplay:none
プロパティによって完全に非表示になっているため、フォーカスを受け取る.ui-helper-hidden
ことはできません。
チェックボックスを<p:selectBooleanCheckbox>
、実際にフォーカス可能な視覚的により魅力的なウィジェットに置き換えるチェックボックスの対応物を見ると、チェックボックスはCSSによって完全に非表示にされているのではなく、絶対にラップされているために非表示になっていることがわかります。クラス内のCSSによって配置されるため、チェックボックスウィジェットによってオーバーレイされます。<div>
position:absolute
.ui-helper-hidden-accessible
<div id="formId:checkboxId" class="ui-chkbox ui-widget">
<div class="ui-helper-hidden-accessible">
<input id="formId:checkboxId_input" name="formId:checkboxId_input" type="checkbox">
</div>
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">
<span class="ui-chkbox-icon"></span>
</div>
</div>
焦点が定まらない「予想される」または「直感的な」動作であるとは考えていません<p:selectBooleanButton>
。もし私があなたなら、このUXの問題をPrimeFacesに報告するでしょう。
それまでの間、これを回避する最善の策は、次のようにencodeMarkup()
PrimeFacesのメソッドをオーバーライドするカスタムレンダラーを作成して、チェックボックスからを削除し、それをとまったく同じようにラップすることです。SelectBooleanButtonRenderer
class="ui-helper-hidden"
<div class="ui-helper-hidden-accessible>
<p:selectBooleanCheckbox>
public class MySelectBooleanButtonRenderer extends SelectBooleanButtonRenderer {
@Override
protected void encodeMarkup(FacesContext context, SelectBooleanButton button) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = button.getClientId(context);
boolean checked = Boolean.valueOf(ComponentUtils.getValueToRender(context, button));
boolean disabled = button.isDisabled();
String inputId = clientId + "_input";
String label = checked ? button.getOnLabel() : button.getOffLabel();
String icon = checked ? button.getOnIcon() : button.getOffIcon();
//button
writer.startElement("div", null);
writer.writeAttribute("id", clientId, "id");
writer.writeAttribute("type", "button", null);
writer.writeAttribute("class", button.resolveStyleClass(checked, disabled), null);
if(disabled) writer.writeAttribute("disabled", "disabled", null);
if(button.getTitle()!= null) writer.writeAttribute("title", button.getTitle(), null);
if(button.getStyle() != null) writer.writeAttribute("style", button.getStyle(), "style");
//input
writer.startElement("div", null); // <-- Added.
writer.writeAttribute("class", "ui-helper-hidden-accessible", null); // <-- Added.
writer.startElement("input", null);
writer.writeAttribute("id", inputId, "id");
writer.writeAttribute("name", inputId, null);
writer.writeAttribute("type", "checkbox", null);
// writer.writeAttribute("class", "ui-helper-hidden", null); <-- Removed.
if(checked) writer.writeAttribute("checked", "checked", null);
if(disabled) writer.writeAttribute("disabled", "disabled", null);
if(button.getOnchange() != null) writer.writeAttribute("onchange", button.getOnchange(), null);
writer.endElement("input");
writer.endElement("div"); // <-- Added.
//icon
if(icon != null) {
writer.startElement("span", null);
writer.writeAttribute("class", HTML.BUTTON_LEFT_ICON_CLASS + " " + icon, null);
writer.endElement("span");
}
//label
writer.startElement("span", null);
writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
writer.writeText(label, "value");
writer.endElement("span");
writer.endElement("div");
}
}
(//input
セクションを見て、<--
コピーペーストされた元のソースコードに追加/削除した行を説明するコメントを追加しました)
実行するには、次のように登録しますfaces-config.xml
。
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.SelectBooleanButtonRenderer</renderer-type>
<renderer-class>com.example.MySelectBooleanButtonRenderer</renderer-class>
</renderer>
</render-kit>
(component-family
およびrenderer-type
値はSelectBooleanButton
コンポーネントから抽出されます)
これは私にとってはうまくいきます。がフォーカスを取得し、<p:selectBooleanButton>
スペースバーを使用してブール状態を切り替えることができます。ただし、フォーカスは視覚的には見えません。これはJavaScript側で解決する必要があります。非表示のチェックボックスがフォーカス<div class="ui-button">
を取得すると、ボタンを表すものはクラスを取得する必要があります。.ui-state-focus
次のjQueryは、それを実現します。
$(".ui-button input[type=checkbox]").focus(function() {
$(this).closest(".ui-button").addClass("ui-state-focus");
}).blur(function() {
$(this).closest(".ui-button").removeClass("ui-state-focus");
});
今では完全に機能します。
実際のPrimeFacesソースコードでは、これはファイルの機能の機能で解決する必要がありinit()
ます。PrimeFaces.widget.SelectBooleanButton
forms.js