문제

안녕하세요 다시 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 휠을 재발 명할 필요가 없도록하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top