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?
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
)
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;
}
}
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>
="{true and ...}"
qui pourrait être une erreur (pas #
)?!empty ...
lorsque je suis tombé dessus.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
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é.
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>