Primefaces p:pickList and the required attribute - jsf

EDIT:
I found the explanation (played around with f:event) and saw that PF has the behaviour I was assuming, namely that the backing bean values of the PF framework themselves are not updated, because the validation phase failed (therefore skipping the update model values phase and directly go to render phase) leaving the source/target list as they were before.
I have the following code:
<p:pickList
id="parentpicklist"
value="#{manager.parent}"
var="entity"
itemValue="#{entity}"
labelDisplay="true"
required="true"
rendered="#{not empty manager.parent.source or not empty manager.parent.target}">
At the end of the page I have a p:commandButton like this:
<p:commandButton
action="#{manager.save}"
value="#{messages.saveLabel}"
title="#{messages.saveHint}"
update="edit-extract" <!-- the picklist resides inside of this component -->
rendered="#{manager.editMode}">
The scenario:
On the page is this picklist and it has its source and target list populated with values, i.e., both are not empty.
Now the problem is the following: When I remove all items from the target list and press 'save', then the validation fails and it says: validation required. So far so good.
THE PROBLEM: It does not only show that the validation failed, but it updates the picklist with its initial values when loading the page.
Is this PF standard behavior?
Because p:commandButton has as default process="#form" (that is why it is validating the picklist which is inside the form). I tried out several stuff to set the targetlist content by my own, e.g., with the onTransfer event.
BUT it does not update the target list --> It looks like the validation fails and the targetlist does not get updated (jsf validation fails and goes directly to the renderResponse phase, i.e., the model values are not updated) and therefore the old resp. initial values are loaded.
Best regards,
ProgrammingIsAwsome

Related

passing datatable object var as parameter in EL expression: how to make it robust?

In Core JavaServer Faces we find the following example for deleting rows out of a DataTable, where tableData.names is a list of Name objects:
<h:dataTable value="#{tableData.names}" var="name" ... />
<h:commandLink value="Delete" action="#{tableData.deleteRow(name)}" />
</h:dataTable>
It comes with a warning that this may not delete the correct row if we use request scope and the list changes "between the rendering of the table and the decoding of the response".
CAUTION: If the value of the data table has request scope, be sure that the data does not change between the rendering of the table and the decoding of the response
(page 226 of the 3rd edition)
Can anyone explain that quote in terms of the JSF lifecycle? If "render response" is the final phase in the JSF lifecycle, where does "decoding the response" fit in? Do they mean the decoding of the following postback REQUEST (which sends a generated ID by which to identify the row and hence the name object)?
And: how can we implement this in a more robust fashion?
The method expression is not evaluated during the request of displaying the form (the encode step as the book is talking about), but during the request of processing the form submit (the decode step as the book is talking about). The inputs and actions of the datatable row are determined on basis of the table's row index. During processing of the form submit, JSF re-iterates over the data model in order to find the submitted values and the invoked actions.
So, if the <h:dataTable value> is tied to a request scoped bean and thus the data model is reinitialized on a per-request basis, then you'll risk the #{item} to actually reference the item at the wrong index during the processing the form submit, because between the requests of displaying the form and submitting the form, the DB might have retrieved a new item, or have removed another item, which would potentially move the desired item to a different index.
To avoid this, the bean needs to be placed in the view scope so that exactly the same datamodel which is initialized in (post)constructor of the initial request will be preserved across postbacks without the need to reinitialize it during the beginning of every single request and thus potentially containing different items or in a different order. The influence is bigger if loading of the datamodel is tied to a specific request parameter under full control of the enduser like a search query.
An alternative, which is actually a bad one in this particular non-idempotent "Delete this item" case, but a good one for the idempotent "Edit this item" case, would be to use a GET link instead. The desired item is immediately rendered as query string parameter of the <a> element.
<h:link value="Edit" outcome="edit">
<f:param name="id" value="#{item.id}" />
</h:link>

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?

JSF Required=Yes not working inside a datatable?

I searched everywhere but could not find a solution to this. I am trying to used
required=yes to validate whether a value is present or not. I am using it inside inputtext.
The problem is it does not work inside a datatable. If I put the text box outside the datatable it works. I am using JSF 1.7 so I don't have the validateRequired tag from JSF 2.0.
I even used a validator class but it is still not working. Does anyone know why does required=yes or validator='validationClass' inside a inputtext inside a datatable is not working.
I appreciate the help.
Thanks.
First of all, the proper attribute values of the required attribute are the boolean values true or false, not a string value of Yes. It's an attribute which accepts a boolean expression.
The following are proper usage examples:
<h:inputText required="true" />
<h:inputText required="#{bean.booleanValue}" />
<h:inputText required="#{bean.stringValue == 'Yes'}" />
As to the problem that it doesn't work inside a <h:dataTable>, that can happen when the datamodel is not been preserved properly (the datamodel is whatever the table retrieves in its value attribute). That can in turn happen when the managed bean is request scoped and doesn't prepare the datamodel during its (post)construction which causes that the datamodel is null or empty while JSF is about to gather, convert and validate the submitted values.
You need to ensure that the datamodel is exactly the same during the apply request values phase of the form submit request as it was during the render response phase of the initial request to display the form with the table. An easy quick test is to put the bean in the session scope. If that fixes the problem, then you definitely need to rewrite the datamodel preserving logic. You could also use Tomahawk's <t:saveState> or <t:dataTable preserveDataModel="true"> to store the datamodel in the view scope (like as JSF2's new view scope is doing).
Finally, JSF 1.7 doesn't exist. Perhaps you mean JSF 1.2?

Skip form validation on command button

I have a JSF page that includes a tree form tag which is rendered depending on some bean property. There are two buttons for next and previous page. I want to skip form validation on the button which goes to the previous page.
I tried the following ways to disable the validation:
Set h:commandButton immediate="true"
Change button by a4j:commandButton ajaxSingle="true" rerender="someparts"
It does not work. Why does the navigation fail when I want to skip validation?
immediate="true" does skip the validation. Make sure you have redeployed successfully, and the there aren't any errors.
I solve problem using a4j:commandButton ajaxSingle="true" reRender=":outhercomponent:formconteningcomponent:component"
reRender needs absolute path to component even if component id unique

rendered attribute on inputText

I have a search form tied to a backing bean that contains 4 input text fields. The design i am working from indicates that the user should be able to see the search results, but they should not be editable. i decided to use the rendered attribute to show the inputs if the managed bean is empty, and to show an output text tag if it's not:
<t:inputText styleClass="inputText" id="name" rendered="#{not searchCriteria.fieldsEntered}"
value="#{searchCriteria.name}" autocomplete="off"></t:inputText>
<h:outputText value="#{searchCriteria.name}" rendered="#{searchCriteria.fieldsEntered}"></h:outputText>
The display part works correctly, but I am noticing that only the first field is stored in the managed bean when more than 1 search field is entered.
I removed a rendered attribute from an inputText, and sure enough that's causing my problems. I can infer what's going on here, but I don't understand why.
I believe in this situation I will just remove the outputText tags and change rendered to disabled. I am just curious why my initial plan is incorrect.
The rendered="false" will cause the input element not being rendered and thus its value will not be submitted to the server side. If you're using a request scoped bean, the initial value will not be set. You'd like to either put the bean in session scope or to add a h:inputHidden along the h:outputText which transfers the value to the subsequent request.
Since you're already using Tomahawk's t:inputText I'd suggest to rather use its displayValueOnly attribute instead of the rendered attribute and a complementary h:outputText.
In a nut:
<t:inputText displayValueOnly="#{searchCriteria.fieldsEntered}" ... />

Resources