2010-12-08 30 views
1

J'ai un formulaire en JSF2 avec 2 cases à cocher (<h:selectBooleanCheckbox>). Au moins l'un d'eux devrait être vérifié. Les deux vérifiés sont également ok, mais quand aucun n'est coché, il devrait y avoir une erreur.JSF2: Comment valider deux cases dépendantes?

Cette validation devrait également fonctionner sur ajax, c'est-à-dire que lorsque l'utilisateur vérifie/décoche, le message d'erreur devrait disparaître/apparaître.

J'ai donc lié les deux cases à UISelectBoolean éléments et validateur ajouté à chacun. Dans le validateur, je vérifie la valeur de la deuxième case à cocher, si elle est fausse, et la case à cocher actuelle est également définie sur faux, un message d'erreur est généré. Smth comme:

if (newValue == false && secondCheckbox.getValue() == false) { 
    throw new ValidationException(); 
} 

problème est lorsque l'utilisateur désélectionne case à cocher sur la page, tandis que l'autre est également sans contrôle, cette fausse valeur ne va pas au modèle, ni événement UISelectBoolean.

Scénario:

  1. Au départ, les deux ne sont pas cochées
  2. utilisateur vérifie checkbox1.
  3. newValue est true, donc cela est valide, va à UISelectBoolean et le modèle.
  4. L'utilisateur décoche la case à cocher checkbox1. Checkbox2 est false, newValue est false, donc exception est levée. En raison de l'échec de la validation, cette valeur false ne va pas au modèle, ni même à l'élément UISelectBoolean.
  5. Vérifications de l'utilisateur checkbox2. True la valeur va au modèle et UISelectBoolean.
  6. L'utilisateur désactive la case à cocher case2. Checkbox1 est toujours décoché sur la page, mais dans le modèle et UISelectBoolean il reste true. Donc la validation passe et il n'y a pas de message d'erreur. Sur la page les deux cases à cocher sont désactivées, mais dans le modèle checkbox1 est toujours true.

Comment résoudre ce problème?

+0

Vous ne pouvez pas utiliser ''? – BalusC

+0

Oui, je ne le savais pas :) Merci! – amorfis

+0

Puis-je ajouter à ? On dirait que f: ajax ne fonctionne pas. – amorfis

Répondre

1

Envisager <h:selectManyCheckbox required="true">. Voici un exemple de coup d'envoi:

<h:form> 
    <h:selectManyCheckbox id="options" value="#{bean.checked}" required="true"> 
     <f:selectItems value="#{bean.options}" /> 
     <f:ajax render="optionsMessage" /> 
    </h:selectManyCheckbox> 
    <h:message id="optionsMessage" for="options" /> 

    <h:commandButton value="Submit" action="#{bean.submit}"> 
     <f:ajax execute="@form" render="@form" /> 
    </h:commandButton> 
    <h:messages globalOnly="true" /> 
</h:form> 

Avec

@ManagedBean 
@RequestScoped 
public class Bean { 

    private List<String> checked; 
    private List<String> options = Arrays.asList("first", "second"); 

    public void submit() { 
     System.out.println("Checked: " + checked); 
    } 

    // ... 
} 

Le f:ajax fonctionne très bien ici. Vous avez probablement utilisé event="click" au lieu de (par défaut) event="valueChange", ce qui entraînera que la coche ne sera pas conservée après le rendu. Le click est appelé juste avant que la marque ne soit affichée visuellement. Le rendu bloquerait la coche visuellement définie.

+0

Merci @BalusC!:) Le seul problème que j'ai avec elle est que crée un

, que j'ai à l'intérieur
d'une autre table. Tout ce que je mets après cet élément est affiché sous le tableau des cases à cocher. Est-il possible de l'afficher "après" la table? Je veux dire au même niveau, à la droite de la table des cases à cocher. – amorfis

+1

Utilisez CSS pour le définir sur 'display: inline;' ou 'float: left;'. 'de Tomahawk peut aussi être utile. Vous pouvez placer [''] (http://myfaces.apache.org/tomahawk-project/tomahawk20/tagdoc/t_checkbox.html) partout où vous voulez. Donc, contrôle total sur le balisage. – BalusC