사용자 지정 렌더러 Ajax 이벤트에 대한 수신기를 트리거하지 않습니다
-
26-12-2019 - |
문제
안녕하세요 다시 JSF 배우스.
사용자 정의 렌더러 및 AJAX 핸들러에 대한 도움을 찾고 있습니다. 우리의 프로젝트는 일반적인 라디오 버튼을 사용할 수 없으며 테이블을 렌더링 할 때 확인란 렌더러를 사용하여 회사 표준에 반대합니다. 제 3 자 구성 요소 라이브러리를 사용할 수 없습니다.
우리는 이제 잘 작동하는 몇 가지 프로젝트에서 사용한 사용자 정의 렌더러를 가지고 있습니다. 그러나이 특정 프로젝트에서는 일부 라디오 버튼에 대해 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));
.
표준 렌더러를 WIH로 생성합니다. 이것은 다음과 같습니다.
<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
}
.
업데이트 : 내 렌더러의 기본 클래스의 디코드 메소드는 다음과 같습니다.
@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 클릭 핸들러는 입력 태그의 이름 및 id 속성 값과 같이 동일합니다. 이로 인해 AJAX 요청이 트리거되어 있지만 리스너는 첫 번째 버전과 마찬가지로 서버 측을 해고하지 않습니다.
아이디어가 있습니까?
해결책
decode()
Renderer
(또는 UIComponent
렌더러가 없으면 렌더러가없는 경우) javax.faces.behavior.event
요청 매개 변수를 기반으로 Ajax 요청을 디코딩하고 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
대신 /repo1.maven.org/maven2/org.glassfish/javax.faces/2.2.0/com/sun/faces/renderkit/html_basic/htmlbasicrenderer.java#htmlbasicrender.decodebehaviors%28javax.faces.context.faceScontext, javax.faces. .component.uicomponent % 29 "rel="nofollow "> HtmlBasicRenderer
및 SelectManyCheckboxListRenderer
휠을 재발 명할 필요가 없도록하십시오.