Question

Re-bonjour les gourous JSF.

Je recherche de l'aide sur les moteurs de rendu personnalisés et les gestionnaires ajax.Notre projet ne peut pas utiliser les moteurs de rendu normaux de boutons radio et de cases à cocher lors du rendu dans les tableaux, ce qui est contraire à nos normes d'entreprise.Nous ne pouvons pas non plus utiliser de bibliothèques de composants tiers.

Nous avons maintenant un moteur de rendu personnalisé que nous avons utilisé dans quelques projets et qui fonctionne très bien.Cependant, sur ce projet particulier, je dois restituer le gestionnaire de clics ajax pour certains boutons radio.En suivant les conseils de la réponse à cette question J'ai ajouté l'appel à RenderKitUtils.renderSelectOnclick(); et bien qu'il semble rendre le même javaScript que le moteur de rendu standard, et en effet, le panneau réseau Firebug affiche la requête sortante, mon écouteur de changement de valeur n'est pas déclenché et je cherche de l'aide pour savoir pourquoi (il se déclenche parfaitement avec le standard moteur de rendu)

Un peu de code :Tout d'abord, la création du gestionnaire ajax (le bouton radio est créé par programme)

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

Avec le moteur de rendu standard, cela produit :

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

et tout va bien.La requête ajax est publiée et mon auditeur côté serveur est renvoyé.

Les parties pertinentes de mon moteur de rendu personnalisé :

 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
}

Mise à jour:La méthode de décodage dans la classe de base de mon moteur de rendu est :

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

Cela donne comme suit :

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

Comme vous pouvez le constater, le gestionnaire de clics javaScript est identique, tout comme les valeurs des attributs name et id des balises d'entrée.Bien que cela déclenche la requête Ajax, l'écouteur n'est pas déclenché côté serveur comme c'est le cas avec la première version.

Des idées ?

Était-ce utile?

La solution

Le decode() méthode du Renderer (ou UIComponent s'il n'y a pas de moteur de rendu) est censé décoder la requête ajax en fonction de javax.faces.behavior.event paramètre de requête et déclencheur ClientBehavior#decode() sur les comportements correspondants des clients.

En gros, la logique est la suivante :

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

Étant donné que vous utilisez RenderKitUtils et la sortie HTML générée contient mojarra.ab(), je suppose que vous utilisez Mojarra.Dans ce cas, il est peut-être plus sage d'étendre votre moteur de rendu personnalisé à partir de RadioRenderer à la place, toute cette logique est déjà implémentée dans HtmlBasicRenderer et SelectManyCheckboxListRenderer pour que vous n'ayez pas besoin de réinventer la roue.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top