Conditional style in JSF when validation has failed in general - jsf

i have h:messages to display error messages, and there's a component that i want its style to change in case of validation error occurs (if any component has a validation error or any validation message is rendered then change the style of this specific component).
i know about the way to change the style if the component has validation errors:
JSF : Better way to check for existence of <h:message for="id"/>
but i want a more general way, to change style if any component in the form is not valid, or in other words any validation message is rendered.
please advise how to accomplish that.

You can use FacesContext#isValidationFailed() to check if validation has failed in general.
<h:outputText ... styleClass="#{facesContext.validationFailed ? 'fail' : 'success'}" />
Alternatively, you can use FacesContext#getMessageList() to check if there are any faces messages. This does not necessarily indicate a general validation failure, there can namely also be global/success messages which are been added in action method.
<h:outputText ... styleClass="#{not empty facesContext.messageList ? 'hasmessage' : 'nomessage'}" />

Related

JSF Required Message being displayed twice

Here is the senorio and codes. JSF Required Message being displayed twice. how can i solve?
<h:outputText value="#{msg['text.surdurulebilir']} :"/>
<p:rating value="#{appraisalBean.newAppraisal.ratingSustainability}" stars="10"
readonly="#{sessionBean.loggedUser.fullName == 'Admin' or sessionBean.loggedUser.fullName == 'Moderator'}"
required="true" requiredMessage="Sürdürülebilirlik Değerlendirilme Alanı Boş Bırakılamaz." id="star5"/>
please check your p:messages tag and both showDetails and showSummary attribute are set to true. That's why two messages are displaying one for summery and another for detail. One more doubt I have you may be adding messages from java file as well

Skip required validation and invoke the application

I asked my question here but I think it lacks some obvious information. Hence I'm posting my question again.
I have a JSF form which has some required validation on h:inputText fields. When submitting the form I want to skip(or ignore) the required validation check and still invoke the application. I do want to do the form data validation and show the errors based on some condition.
Basically I want to skip the validations and invoke the application when the form is submitted using an ajax call and do the validation when the form is submitted via clicking a submit button.
Just put that condition straight in the required attribute.
<h:inputText ... required="#{someCondition}" />
It namely just accepts any EL expression like as many other attributes. Many starters think that you can only hardcode a "true" or "false" string in it. This is untrue.
For example, when you want to let it evaluate true only when the save button is actually pressed:
<h:inputText ... required="#{not empty param[save.clientId]}" />
...
<h:commandButton value="Cancel" ... />
<h:commandButton binding="#{save}" value="Save" ... />
(note: code is complete as-is, you do not need to bind it to a bean property)
This way the required attribute only evaluates true when the save button is pressed and it evaluates false for any other button or ajax event listener.

h:inputText not updating from bean automatically

I have an h:inputText in my form. The value is not properly updating when I update its panelGroup. JSF version is 2.1.13.
If I used disable="true" OR displaying the bean value in h:outputText OR refresh the page its updating properly. But by default its not happening.
<span style="min-width: 100px;"> First Name: #{NewPatient.newPatientBean.firstName}</span>
<h:inputText id="fname"
value="#{NewPatient.newPatientBean.firstName}"
onchange="initialCaps(this);" maxlength="50">
<f:ajax execute="#this" event="blur"/>
</h:inputText>
In the above code
First Name: #{NewPatient.newPatientBean.firstName} is properly updating but the inputText is not.
Kindly let me know the mistake and solution for the above issue. Thanks in advance.
That will happen when a validation error occurred during the current or previous postbacks. The input component will then not redisplay the model value, but only the initially submitted value when the component itself failed validation or the local value when another component in the same form failed validation.
As the concrete functional requirement is completely absent in the question, it's not possible to propose the right solution for this. So here's just a link which explains the problem more generically which should give new insights as to the cause and the solution: How can I populate a text field using PrimeFaces AJAX after validation errors occur?

Why was "immediate" attribute added to the EditableValueHolders?

Initially immediate flag was only intended for ActionSource interface. But later on it was added to the EditableValueHolder interface also. What was the reason for design decision ?
It's to be used to prioritize validation on several EditableValueHolder components in the same form.
Imagine a form containing input components with immediate="true" as well as input components without this attribute. The immediate inputs will be validated during apply request values phase (which is one phase earlier than usual). The non-immediate inputs will be validated during validations phase (which is the usual phase). If validation fails for at least one of the immediate inputs, then the non-immediate inputs won't be converted/validated at all and thus won't generate any conversion/validation error messages. This is particularly useful in forms with complex validation rules where it doesn't make sense to validate component Y when validation for (immediate) component X has failed anyway.
When used in combination with immediate="true" on a command button in the same form, this will cause all non-immediate inputs being completely skipped. A good real world example is a login form with 2 fields "username" and "password" with required="true" and 2 buttons: "login" and "password forgotten". You could put immediate="true" on the "username" field and the "password forgotten" button to skip the required="true" check on the password field.
In the dark JSF 1.x ages, the immediate="true" was also often (ab)used as a hack in combination with valueChangeListener and FacesContext#renderResponse(), more than often in cascading dropdown lists. Long story short, here's an old blog article on that. To the point, it enables developers to execute a backing bean method on change of a <h:selectOneMenu> without that all other inputs in the same form are been validated. But these days, with the ajax awesomeness, this hack is unnecessary. You can find a concretre example of this case at the bottom of our <h:selectOneMenu> wiki page.
These days, the immediate="true" is still often (ab)used in order to have a specific button which completely bypasses all other inputs, such as a logout button in a "God-form" antipattern (whereby everything is been thrown together in a huge <h:form>), or a cancel button which incorrectly submits the form. Such a button would break when you start to actually need the immediate="true" the right way on one of the inputs. You'd better put such a logout button in its own form, or to change it to process only itself (process="#this" in PrimeFaces). And you'd better change such a cancel button to just refresh the page synchronously by <h:button value="Cancel" />. This works fine if the form is tied to a request/view scoped bean and browser caching is disabled on dynamic pages.
See also:
Should immediate="true" never be used when dealing with an AJAXified JSF 2.0 component?
Trying to understand immediate="true" skipping inputs when it shouldn't

Trying to understand immediate="true" skipping inputs when it shouldn't

Just when I thought I had understood immediate... *sigh*
Consider the following JSF page:
<h:inputText value="#{testBean.text}" required="true" />
<h:commandButton actionListener="#{testBean.doFoo}" value="Do Foo" />
<h:commandButton immediate="true" actionListener="#{testBean.doBar}" value="Do Bar" /><br />
<h:outputText value="#{testBean.didSomething}" />
And this backing bean:
public class TestBean {
private String didSomething = "Nothing done yet";
// + getter
public void doFoo() {
didSomething = "Did foo!";
}
public void doBar() {
didSomething = "Did bar!";
}
From all I read about immediate I would expect the following:
When trying to do foo while not providing a value for the input field, the action is never executed because during processValidationsPhase an error occurs, resulting in the page to be re-rendered directly after this phase with an error message. The value of the didSomething remains unchanged. (This works as expected)
When trying to do bar while not providing a value for the input field, the action is executed during applyRequestValuesPhase because of the immediate attribute. The variable didSomething is changed. (This works as expected)
On what happens next, this description states:
"A null return value (as outcome of the action method) causes processing to continue as normal, ie non-immediate components are validated then update-model is executed (if no validation errors occurred). For an action listener method that returns void, it is necessary to call facesContext.renderResponse(); if the normal flow is not desired."
From this I had the idea that processing continues as normal (as my action method does neither return an outcome nor force renderResponse()), resulting in the same validation error. Only difference would be that it occurs after setting didSomething. However, this does not happen. Instead, it feels like the site still skips all remaining phases, with the input field not being touched. It re-renders without error message.
Can someone explain to me where my understanding of how this works is amiss?
With immediate="true" on the button, the action is indeed invoked during apply request values phase and all the remaining phases are skipped. That's also the sole point of this attribute: process (decode, validate, update and invoke) the component immediately during apply request values phase.
All inputs which do not have immediate="true" are ignored anyway. Only inputs which do have immediate="true" are also processed, but this happens also during apply request values phase. Why should the remaining phases be invoked if everything has already taken place in the apply request values phase?
In the Debug JSF lifecycle article you can find the following summary which should enlighten when to (not) use the immediate"true":
Okay, when should I use the immediate attribute?
If it isn't entirely clear yet, here's a summary, complete with real world use examples when they may be beneficial:
If set in UIInput(s) only, the process validations phase will be taken place in apply request values phase instead. Use this to prioritize validation for the UIInput component(s) in question. When validation/conversion fails for any of them, the non-immediate components won't be validated/converted.
If set in UICommand only, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s). Use this to skip the entire processing of the form. E.g. "Cancel" or "Back" button.
If set in both UIInput and UICommand components, the apply request values phase until with update model values phases will be skipped for any of the UIInput component(s) which does not have this attribute set. Use this to skip the processing of the entire form expect for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required but non-immediate password field.
See also:
Why was "immediate" attribute added to the EditableValueHolders?

Resources