カスタムレンダラーがajaxイベントのリスナーをトリガーしない
-
26-12-2019 - |
質問
こんにちは再情達.
私はカスタムレンダラーとajaxハンドラの助けを探しています。私たちのプロジェクトでは、通常のラジオボタンとチェックボックスレンダラーをテーブルでレンダリングするときに使用することはできません。サードパーティのコンポーネントライブラリを使用することもできません。
いくつかのプロジェクトで使用したカスタムレンダラーがありますが、これは正常に動作します。しかし、この特定のプロジェクトでは、いくつかのラジオボタンのajaxクリックハンドラをレンダリングする必要があります。答えのアドバイスに続いて この質問 私は呼び出しを追加しました RenderKitUtils.renderSelectOnclick();
そして、それは標準のレンダラーと同じjavaScriptをレンダリングするように見えますが、実際には、firebug network panelは送信要求を表示しますが、私の値変更リスナーは発
いくつかのコード:まず、ajaxハンドラの作成(ラジオボタンはプログラムで作成されます)
AjaxBehavior valueChangeAction = (AjaxBehavior) FacesUtils.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
valueChangeAction.addAjaxBehaviorListener(new ProbeQuestionListener(currentQuestion, "probeDiv" + questionNumber,
probeDiv));
selectUI.addClientBehavior("valueChange", valueChangeAction);
valueChangeAction.setRender(Collections.singletonList("probeDiv" + questionNumber));
標準のレンダラーを使用すると、これが生成されます:
<table id="answer_1" class="marginLeft1a">
<tbody>
<tr>
<td>
<input id="answer_1:0" type="radio" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" value="0" name="answer_1">
<label for="answer_1:0"> Yes</label>
</td><td>
<input id="answer_1:1" type="radio" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" value="1" name="answer_1">
<label for="answer_1:1"> No</label>
</td>
</tr>
そして、すべてが順調です。Ajaxリクエストが投稿され、サーバー側のリスナーが起動されます。
私のカスタムレンダラーの関連部分:
public void encodeEnd(final FacesContext p_context, final UIComponent p_component) throws IOException {
/* set up convenience fields */
context = p_context;
component = p_component;
componentId = component.getClientId(context);
// rendering divs etc omitted.
while (iterator.hasNext()) {
final UIComponent childComponent = iterator.next();
// irrelevant code omited
if ("javax.faces.SelectItem".equals(childComponent.getFamily())) {
renderSelectItem(idIndex, childComponent);
idIndex++;
}
}
}
private void renderSelectItem(final int p_idIndex, final UIComponent p_childComponent) throws IOException {
// unrelated code omitted
writer.startElement("input", component);
writer.writeAttribute("type", getInputType(), null);
writer.writeAttribute("id", p_childComponentId, "id");
writer.writeAttribute("name", componentId, "clientId");
RenderKitUtils.renderSelectOnclick(context, component, false);
writer.endElement("input");
// unrelated code omitted
}
更新:私のレンダラーの基本クラスのdecodeメソッドは次のとおりです:
@Override
public void decode(final FacesContext p_context, final UIComponent p_component) {
final Map<String, String> valuesMap = p_context.getExternalContext().getRequestParameterMap();
final UIInput input = (UIInput) p_component; // NOSONAR
final Object value = valuesMap.get(input.getClientId(p_context));
// System.out.println("radio button decode: found " + value);
input.setSubmittedValue(value);
}
これは次のようにレンダリングします :
<span class="marginLeft1a" id="answer_1">
<label for="answer_1:0">
<input type="radio" value="0" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" name="answer_1" id="answer_1:0">
Yes
</label>
<label for="answer_1:1">
<input type="radio" value="1" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" name="answer_1" id="answer_1:1">
No
</label>
</span>
ご覧のとおり、javaScriptのクリックハンドラーは、inputタグのname属性とid属性の値と同じです。これによりAjaxリクエストがトリガーされますが、リスナーは最初のバージョンと同じようにサーバー側では起動されません。
何か考えは?
解決
ザ- decode()
の方法 Renderer
(または UIComponent
レンダラがない場合)に基づいてajaxリクエストをデコードすることになっています javax.faces.behavior.event
要求パラメータとトリガ ClientBehavior#decode()
一致するクライアントの動作に。
基本的に、ロジックは次のとおりです:
Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
if (!behaviors.isEmpty()) {
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
String behaviorEvent = params.get("javax.faces.behavior.event");
if (behaviorEvent != null) {
List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);
if (behaviorsForEvent != null && !behaviorsForEvent.isEmpty()) {
String behaviorSource = params.get("javax.faces.source");
if (isBehaviorSource(context, behaviorSource, component.getClientId())) {
for (ClientBehavior behavior: behaviorsForEvent) {
behavior.decode(context, component);
}
}
}
}
}
あなたが使用しているという事実を考えると RenderKitUtils
生成されたHTML出力には次のものが含まれます mojarra.ab()
, 、私はあなたがMojarraを使用していると仮定します。その場合、カスタムレンダラーを次のものから拡張する方が賢明でしょう RadioRenderer
代わりに、このロジックはすべてすでに実装されています HtmlBasicRenderer
と SelectManyCheckboxListRenderer
あなたが車輪を再発明する必要がないように。