2009-06-29 8 views
1

Je dois valider deux champs d'entrée utilisateur l'un par rapport à l'autre dans la couture. Field1 doit être supérieur à Field2 pour chaque ligne d'une balise ui: repeat. A partir de maintenant, j'ai les deux champs enveloppés dans un tag s: decorate qui enveloppe toutes les entrées dans une balise s: validateAll. Cela me permet de faire flotter un message d'erreur à droite des champs si la validation échoue pour l'un d'entre eux.Comment invalider un champ en couture?

Par exemple (je ne peux pas insérer une image, donc je dois utiliser l'image ascii, pardonner s'il vous plaît de faible qualité, l'italique indique le texte en rouge):

Label: | Jaune | 0 |% Rouge: | 0% | | Le jaune et le rouge doivent être compris entre 0 et 100 et le jaune doit être supérieur au rouge.

Label: | Jaune | 0 |% Rouge: | 0% | | Le jaune et le rouge doivent être compris entre 0 et 100 et le jaune doit être supérieur au rouge.

Les deux contrôles et le décor xhtml sont ci-dessous. NOTE: La validation "valeur comprise entre 0 et 100" est déjà prise en compte via l'annotation d'hibernation. Je dois seulement besoin de savoir comment valider ces 2 champs les uns contre les autres pour s'assurer que le jaune est plus grand que le rouge, et que le message d'erreur s'affiche toujours.

Ma solution désirée serait de définir la propriété # {invalid} pour la balise s: decorate correspondante, ainsi le message d'erreur apparaîtra, mais je prendrai des idées.

Les entrées:

<table> 
    <ui:repeat value="#{action.List}" var="var"> 
     <s:decorate template="/layout/decorateMultipleInputs.xhtml" > 
      <ui:define name="label"> 
       Label: 
      </ui:define> 
      <ui:define name="input"> 
       <h:panelGrid columns="8" frame="border"> 
        <h:outputText value="Yellow:" /> 
        <h:inputText value="#{var.yellow}" style="width:25px; text-align:right" maxlength="3"/> 
        % 

        <h:outputText value="Red:" /> 
        <h:inputText value="#{var.red}" style="width:25px; text-align:right" maxlength="3"/> 
        % 
       </h:panelGrid> 
      </ui:define> 
      <ui:define name="message">Yellow and Red must be between 0 and 100, and Yellow must be greater than Red. 
      </ui:define> 
     </s:decorate> 
    </ui:repeat> 
</table> 

et decorateMultipleInputs.xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:ui="http://java.sun.com/jsf/facelets" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core" 
      xmlns:s="http://jboss.com/products/seam/taglib"> 
<tr> 
<td>   
    <s:label styleClass="#{invalid?'error':''}"> 
     <ui:insert name="label"/> 
     <s:span styleClass="required" rendered="#{required}">*</s:span> 
    </s:label> 
</td> 
<td> 
    <s:validateAll> 
     <ui:insert name="input"/> 
    </s:validateAll> 
</td> 
<td> 
    <s:div styleClass="error" rendered="#{invalid}"> 
     <h:graphicImage value="/images/error.gif" /> 
    </s:div>  
</td> 
<td> 
    <s:div styleClass="error" rendered="#{invalid}"> 
     <ui:insert name="message"/> 
    </s:div>  
</td> 
</tr> 
</ui:composition> 

Répondre

1

J'attacherait votre propre validateur JSF personnalisé au <h:inputText/> rouge

<h:inputText value="#{var.red}" style="width:25px; text-align:right" maxlength="3"> 
    <f:validator validatorId="rowValidator"/> 
</inputText> 

Mettre en œuvre un validateur JSF (puisque vous utilisez Seam vous pouvez utiliser l'annotation @Validator).

@Validator 
public class RowValidator implements javax.faces.validator.Validator 
{ 
    public void validate(FacesContext context, UIComponent component, Object value) 
     throws ValidatorException 
    { 
     <snip/> 
    } 
} 

La clé est l'objet UIComponent ici passé à la méthode validate(). C'est le <h:inputText/> auquel vous avez lié le validateur. De là, vous pouvez appeler le getParent() pour obtenir le parent <h:inputText/> (<h:panelGrid/>). Vous pouvez maintenant énumérer les objets <h:panelGrid/> les enfants pour trouver le <h:inputText/> jaune, récupérer la valeur passée pour et comparer avec le paramètre value transmis à la méthode validate().

Si le jaune est moins rouge que vous pouvez faire ce qui suit dans votre méthode validate():

FacesMessage message = new FacesMessage(); 
message.setDetail("Yellow must be greater than red"); 
message.setSummary("Yellow must be greater than red"); 
message.setSeverity(FacesMessage.SEVERITY_ERROR); 
throw new ValidatorException(message); 
+0

Excellente idée, je vais essayer, merci! –

+0

Cela fonctionne très bien! C'est comme si on passait par le parent pour arriver aux commandes de la fratrie, mais cela fonctionne assez simplement pour être utile. Merci encore! –

+0

Soyez juste conscient du couplage étroit entre le balisage et le validateur. Si la marque change, cela peut casser le validateur. :) – Drew

0

Seam ne contient pas encore une façon de faire la validation multi-terrain. C'est actuellement sur le registre pour les WebBeans JSR-299, mais il n'y a pas de manière propre et nette comment faire cela.

Vous pouvez y parvenir en validant après une forme soumettre dans le cadre de votre gestionnaire d'action habituelle. c'est à dire.

public String processRedsAndYellows() { 
    for(RedYellow var : ActionBean.getList()) { 
     if(var.getYellow() <= var.getRed()) { 
     messages.addMessage("All Yellows must be greater than Reds"); 
     return null; 
     } 
    } 
    return "success"; 
} 

Ou quelque chose à cet effet. :)

+0

Merci pour votre réponse rapide, j'avais peur que je devais aller dans cette voie. :) –

Questions connexes