web-dev-qa-db-fra.com

JSF ignorer la validation requise sans immédiat = true

J'ai plusieurs formulaires, où j'ai des champs obligatoires et des champs optionnels.

Pour soumettre un tel formulaire, je demande l'exécution de la validation sur l'attribut required, ce qui fonctionne très bien . Pour annuler un tel formulaire, j'utilise l'attribut immediate="true" sur le p:commandbutton , ce qui rend son action possible pendant la phase Apply Request Values ​​ comme indiqué ici: Comment ignorer la validation lorsqu’un bouton spécifique est cliqué?

Cependant, pour les formulaires volumineux, je souhaite fournir à l'utilisateur un bouton Enregistrer afin qu'il puisse continuer plus tard.

Pour ne sauvegarder que l'état actuel, je souhaite également ignorer la validation de l'attribut requis. Cependant, utiliser immediate="true" ne fonctionne pas, car ma méthode de sauvegarde simple n'enregistre rien, car le cycle de vie JSF ne frappe jamais la phase "UpdateModelValues". (Selon http://www.javacodegeeks.com/2012/01/jsf-and-immediate-attribute-command.html )

Alors, comment contourner la vérification requise sans ignorer la moitié du cycle de vie? 

39
dognose

Chaque bouton crée une entrée dans la liste de paramètres tant qu'elle est membre du formulaire. J'ai donc simplement appliqué une vérification de la présence de cette entrée au paramètre "required":

<h:form id="form" prependId="true">
...
<p:inputText id="someId"
    required="#{param['form:save']==null}" ... />
...
<p:commandButton id="save" value="Save" />
<p:commandButton id="submit" value="Submit" />
<p:commandButton id="cancel" value="Cancel" immediate="true" />
</h:form>

Lorsque je clique sur «Soumettre», le param['form:save'] est NULL, ce qui transforme ensuite l'expression en true afin que la validation soit exécutée.

Lorsque je clique sur "Enregistrer", le param['form:save'] est NOT NULL (mais vide!), Ce qui donne false et la validation est donc ignorée. (Ou supposons que JSF pense que ce n'est pas un champ obligatoire à cause de l'expression évaluée à false)

62
dognose

si vous voulez ignorer la validation lorsque vous cliquez sur le bouton, ajoutez-y facilement un paramètre à celui-ci. Exemple:

<p:commandButton value="button1" action="#{bean.action()}" >
   <f:param name="skipValidator" value="true"/>
</p:commandButton>

Ensuite, dans le validateur, vous pouvez lire ce paramètre et s'il est vrai, ignorez-le:

@FacesValidator("com.validators.MyValidator")
public class MyValidator implements Validator{

  public void validate(FacesContext ct, UIComponent co, Object obj) throws ValidatorException { 
    if(!continueValidation()){
      return;
    }
    // validation process
  }

protected boolean continueValidation() {
    String skipValidator= FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("skipValidator");
    if (skipValidator != null && skipValidator.equalsIgnoreCase("true")) {
      return false;
    }
    return true;
  } 
}
5
Juraj

C'est une excellente question et une réponse très utile. Cette approche évite beaucoup de tracas avec immediate="true".

J'aimerais ajouter cette information (mais je ne suis pas autorisé à commenter pour le moment). Vos exemples de code semblent nécessiter JSF 2.0 ou supérieur (corrigez-moi). Si vous êtes comme moi condamné à utiliser JSF 1.1/1.2, tenez compte des modifications/ajouts suivants:

<h:form id="form">
...
<p:inputText id="someId" required="#{!empty param['save']}" ... />
...
<p:commandButton id="save" value="Save" />
</h:form>
  • Il n'y a pas d'attribut prependId dans JSF 1.1
  • Par conséquent, dans le [...] paramètre, vous devez uniquement spécifier l'ID du bouton.
  • Vous utilisez une syntaxe ="{true and ...}" qui pourrait être une erreur (pas #)?
  • Comme vous pouvez le constater à partir de votre propre historique d'édition, la logique "null or not null" n'est pas très intuitive :) C'est pourquoi j'ai tout de suite aimé la version !empty ... lorsque je suis tombé dessus.
4
SebastianH

Une alternative à ce que d’autres ont proposé est d’utiliser une variable BeanValidator personnalisée qui validera le formulaire si, par exemple, vous avez cliqué sur le bouton avec l’enregistrement id. Tout autre bouton non implicitement défini pour effectuer la validation ne validera pas, mais simplement transmettra vos données disponibles. Trouvez l'exemple complet Nice and clean here

1
Given Nyauyanga

Dans mon cas, je n'ai pas trouvé le clientId du bouton dans les paramètres mais j'ai trouvé ceci param['javax.faces.source'] = buttonClientId dans le requestmap. La valeur sera le clientId du bouton cliqué.

0
Shady Aziz

J'utilise skipValidators pour un tel cas (en supposant que toutes les validations sont ignorées). Code de omnifaces

<h:form>
  <h:dataTable value="#{bean.items}" var="item">
    <h:column>
        <h:inputText value="#{item.value}" required="true" />
    </h:column>
  </h:dataTable>
  <h:commandButton value="add new row" action="#{bean.add}">
    <o:skipValidators />
  </h:commandButton>
  <h:commandButton value="save all data" action="#{bean.save}" />
  <h:messages />
</h:form>
0
dr0ps