required fields skip reactions to user input - jsf

If there are empty required fields in the form, they prevent me both from setting the values via code and hide/show other fields depending on current user input.
I broke down my problem to a tiny example:
<h:inputText label="Name" value="#{req.test}" required="true"/>
<h:inputText label="Details" value="#{req.tests2}" readonly="true" required="true"/>
<h:selectBooleanCheckbox label="Hide field" value="#{req.bool1}"/>
<ui:fragment rendered="#{not req.bool1}">
<h:inputText label="Hidden" value="#{req.test3}" required="true"/>
</ui:fragment>
I have required fields in my form, but if the user chooses to first set the checkbox, I want the hidden field to appear even if the validation failed. And I want the fields to be marked as invalid, so I cannot use immediate.
The problem is that while processing validation, renderResponse is called in the jsf lifecycle. So the update model values phase is skipped and I cannot react to the user input.
In addition to that: If I fill all required fields with the checkbox checked (the form would be valid) and uncheck the checkbox (a required field "Hidden" appears), I cannot just make "Hidden" to disappear again by checking the checkbox, because "Hidden" cannot be empty as required field. Even if I say required="#{not req.bool1}" it does not work, as the checkbox value never reaches my model because the update model value phase is skipped.
What we did now is wrap the faces context to prevent a call to renderResponse() during the validation phase from setting the flag. (Yes, dangerous, yes, I do need a better way to do that.) Now finally the model is up to date, BUT:
The required fields still remain empty, because for some reason jsf decided required fields do not need to get their value from my model as long as they are empty/invalid.
How can I make my model values to appear in the required fields?
Is there a simple and proper way to solve my ignore-invalid-state-and-continue-with-phases-properly problem, other than basically preventing renderResponse() from happening?

So the answer to the first question is: reset the value and THEN update, then I get my values to show in the required fields. Thanks Vasil!
As for the second question: I wonder how it's possible no one ran into the problem before. Is it just me? Well, I guess I'm not getting the point and am using the life cycle wrong or something. But I was really thinking the view should respond to user input, even it some fields are still empty. The user is still inserting data after all, and we're not moving on, yet. The fields are allowed to be empty in that state.
I guess that's the point and my "required" means something else than the jsf "required". I still don't get the standard validation process in that regard...
But I have a dirty workaround for my problem, so I'll mark the question as answered.

Related

jsf get disabled field values in requestscoped bean

Could you please give me some directions on how to pass values from disabled or readonly input fields in xhtml page to requestscoped bean?
I thought that I can bypass jsf checking the field state by disabling
fields in javascipt code on form open and then submit form, but that
did not help too.
I cannot use view scope, because I would have to set then almost
every page in my application in view scope.
It is very inconvenient to use hidden fields for this purpose,
because it would double the number of fields on the page.
Maybe I have missed some clean solution?
Thank you in advance for any help.
Disabling fields using JavaScript didn't work probably because you didn't enable them just before sending a form. Values of disabled fields are not sent (see input documentation).
For example the following code works perfectly well:
<h:form>
<h:inputText id="disabledinput" styleClass="disabled"
value="#{someBean.property}"></h:inputText>
<h:outputScript>
$('.disabled').attr('disabled', 'disabled');
</h:outputScript>
<h:commandButton action="#{someBean.action}"
onclick="$('.disabled').removeAttr('disabled'); return true;"
value="Submit" />
</h:form>
onclick attribute executes JavaScript code that enables input just before sending the form.
If you use AJAX request you have to restore disabled state using oncomplete or similar.
The problem with this solution is that user can manipulate the value. E.g. she/he can use javascript console in a browser to change the input to enabled or use some tool (e.g. curl) to prepare or tamper request. So if the value is sensitive or should never be changed by the user consider storing the value in the session.
IMHO if the value was provided by the user in one of the previous steps then it doesn't matter that much. However, if value is calculated (like total value or something) you should not depend on its value as users could change it. Personally I would prefer to store the value on server side (in session or in flash).

JSF Lifecycle with immediate=true

When I read article Listen and debug JSF lifecycle phases
wrtten by #BalusC, I have some trouble understanding the article.
While Add immediate="true" to UIInput and UICommand, It says:
Note for all components with immediate: as the Update model values phase is skipped, the value bindings aren't been set and the value binding getters will return null. But the values are still available...
Note for other components without immediate: any other UIInput components inside the same form which don't have immediate="true" set will not be converted, validated nor updated, but behind the scenes the inputComponent.setSubmittedValue(submittedValue) will be executed before the action() method will be executed. You can retrieve...
Is that means no matter with or without immediate, the Update model values phase will always skipped because the immediate="true" in the h:commandButton? If so, the value in backing bean will not change, right?
However, in the last paragraph of the article, it summarized "when to use immediate=true" and mentioned:
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 except for certain fields (with immediate). E.g. "Password forgotten" button in a login form with a required and immediate username field and a required but non-immediate password field.
I am confused because I thought Process validations Phase and Update model values Phase are skipped no matter there are/aren't immediate once you set immdediate=true in h:commandButton in the same form.
I must misunderstood something, please help me clarify it.
Thanks in advance!
That part indeed needs clarification.
What is meant in the summary, is the job which is normally executed in the mentioned phases (i.e. applying request values, processing validations and updating model values), even though they happen in the apply request values phase.
I have updated the article accordingly.

h:inputText and h:outputText show different values for same (EL) field

I've got a very strange problem here. I have a rich:popupModal which is used to edit an entity. Some of the input fields on that modal use a validator. There is also some ajax going on which is used to update other fields on that modal. There is e.g. a 'Number of packages' field, a weight per package field and a total weight field. If you change the number of packages it will update the total weight field, etc.
Now when e.g. the user entered a value that is too high, the validation fails, an error message is shown. The user can either correct the values on the modal or press cancel.
When he cancels the entity is reset to the values it had before the edit (there were some ajax changes so I need to reset those). The modal closes and a table is showing the correct (reset) values for that entity.
Now the strange thing happens. When I edit another entity the modal is suddenly showing the old values for the previous entity (the ones that did not pass validation).
To debug this I was checking whether the correct instance of the commodity is used so I added h:outputText fields for some of the values and I am also showing the System hash of the entity on the modal.
I've got e.g.
<h:outputText value="#{backingBean.entity.description}"/> which prints 'Stuff 1'
and then
<h:inputText value="#{backingBean.entity.description}"/> which prints 'Stuff 3' (the first entity I've edited). WTH?
I've added getter and a dummy setter on the entity to return the System.identityHashCode. And h:outputText and h:inputText use indeed a different entity but how is that possible when the EL is #{backingBean.entity.hashId} in both cases?
I've used the richfaces a:log to see whether that shows any errors but it all looks okay.
I have tried to clear the modal on cancel (rerender it with no components in) but that didn't fix the problem either. I've tried it on both Chrome and Firefox. Both have the same problem.
What could be going on here?
My environment: JSF 2, Seam 2.3, RichFaces 4.3.3, JBoss EAP 6.1

How to avoid APPLY_REQUEST_VALUES phase for particular event

I have a requirement wherein the form displays many input fields from model object.
And on one of the fields an external plugin is invoked and the value of that field is directly changed in the model by that plugin (not changed in UI form field), now I would like to reRender that panel so that changed value (from model object) is displayed onto UI form field.
Verified everything and plugin is also able to change value in the model and its also triggering reRender of the panel. When reRender, what happens is the values in UI form are applied to model and model object loses the value (set by plugin) and when panel is refreshed I would still see blank Field.
Is there a way that only for this event I bypass APPLY_REQUEST_VALUES so that values in model are displayed? Or is there a better solution for this?
Regards,
Satya
You can use immediate="true" for this.
<a4j:support ... immediate="true" />
This way only the current component will be processed.
Another way is to just proceed to render response immediately in the value change listener so that the Update Model Values (and Invoke Action) phase is skipped.
FacesContext.getCurrentInstance().renderResponse();

Using `immediate` for a cancel button but saving only some fields

I have a JSF 1.2 Form which is composed of several parts.
I have validation with required tag turned on.
I want to be able to clear a certain part of the form which has required fields so on the 'clear' button i used the immediate tag.
Now the challenge - When pressing the 'clear' button all the values that were filled since the last submission are restored to the last submitted state while I would like only the certain part of the form to be affected. (Meaning, all the values that are not in that part of the form should be sumbitted although the button pressed is immediate)
Is there a way to do this?
EDIT - Can I submit a value after every time it was filled? This might be a solution.
Thanks!
If you want to take some fields along with the cancel button with immediate="true", then you should also put immediate="true" on those fields.
If you want to skip validation on those fields as well, then you need to change required="true" to required="#{empty param['formId:cancelButtonId']}" so that it is only required when the cancel button is not been used to submit the form.
As to submitting the values on change, that's best to be achieved with ajax in combination with a value change listener. To achieve that you would need to upgrade to JSF 2.0 or to introduce an ajaxified JSF component library.

Resources