Pregunta

Hola de nuevo JSF Gurus.

Estoy buscando ayuda sobre renderizadores personalizados y controladores ajax.Nuestro proyecto no puede utilizar los renderizadores normales de botones de opción y casillas de verificación, ya que se representan en tablas y esto va en contra de nuestros estándares corporativos.Tampoco podemos utilizar bibliotecas de componentes de terceros.

Tenemos un renderizador personalizado que hemos usado en algunos proyectos y ahora funciona bien.Sin embargo, en este proyecto en particular, necesito representar el controlador de clic ajax para algunos botones de opción.Siguiendo el consejo de la respuesta a esta pregunta He añadido la llamada a RenderKitUtils.renderSelectOnclick(); y aunque parece renderizar el mismo javaScript que el renderizador estándar y, de hecho, el panel de red de Firebug muestra la solicitud saliente, mi oyente de cambio de valor no se activa y estoy buscando ayuda para saber por qué (se activa perfectamente con el renderizador estándar renderizador)

Algún código:En primer lugar, la creación del controlador ajax (el botón de opción se crea mediante programación)

          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));

Con el renderizador estándar, esto produce:

<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>

y todo está bien.La solicitud ajax se publica y el oyente del lado del servidor se activa.

Las partes relevantes de mi renderizador personalizado:

 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
}

Actualizar:El método de decodificación en la clase base para mi renderizador es:

    @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);
}

Esto se representa como:

<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>

Como puede ver, el controlador de clics de JavaScript es idéntico, al igual que los valores de los atributos de nombre e identificación de las etiquetas de entrada.Aunque esto desencadena la solicitud de Ajax, el oyente no se activa en el lado del servidor como ocurre con la primera versión.

Algunas ideas ?

¿Fue útil?

Solución

El decode() método de la Renderer (o UIComponent si no hay un renderizador) se supone que decodifica la solicitud ajax en función de javax.faces.behavior.event solicitar parámetro y disparador ClientBehavior#decode() sobre los comportamientos coincidentes del cliente.

Básicamente, la lógica es la siguiente:

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);
               }
           }
        }
    }
}

Dado el hecho de que estás usando RenderKitUtils y la salida HTML generada contiene mojarra.ab(), Asumiré que estás usando Mojarra.En ese caso, quizás sea más prudente ampliar su renderizador personalizado desde RadioRenderer en cambio, que tiene toda esta lógica ya implementada en HtmlBasicRenderer y SelectManyCheckboxListRenderer para que no tengas que reinventar la rueda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top