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();
Related
I have a local Web Application developed with JDK 8, JSF 2.2 (implementation provided by JBoss), Spring 4.2 and Primefaces 6.2
In the application, I have one XHTML page for edit some fields of an object that is instance of a class named SiepRoEncabezado. One of those fields is an instance of SiepRpaPescador.
Until yesterday, I had one <p:selectOneMenu> contained in a form that is contained in a modal dialog in order to select one SiepRpaPescador object. The modal itself has 2 submit <p:commandButton> (one for save the changes and one for clean the form) and some aditional input fields.
The modal is developed in such manner that it closes automatiquely when the data is successfully edited after I push the save button.
The modal with the <p:selectOneMenu> worked fine, but due to the fact that there are too many select items to be handled in terms of memory usage, I was forced to replace the <p:selectOneMenu> by the following component:
<p:autoComplete dropdown="true"
id="rpaAutoComplete"
value="#{correccionROBean.tmpPescador}"
var="itemRpa"
itemLabel="#{itemRpa.nmPescador.concat(' ').concat(itemRpa.nmPaterno).concat(' ').concat(itemRpa.nmMaterno)}"
itemValue="#{itemRpa}"
completeMethod="#{correccionROBean.filtrarRpa}"
minQueryLength="4"
maxResults="10"
forceSelection="true" />
There, tmpPescador is a bean in the Managed Bean CorreccionROBean.
The complete method there works fine and the selection items are displayed as desired.
However, after I select one item in the <p:autoComplete> component and push the button to save the changes, it does nothing at all. Also, it does not display an error message and it does not throw any exception. What is worst, if I try to debug the action listener method in the button to save changes, it does nothing, it's like the action listener method is not called at all.
I put an <p:ajax> tag hoping to solve the problem with no avail:
<p:autoComplete dropdown="true"
id="rpaAutoComplete"
value="#{correccionROBean.tmpPescador}"
var="itemRpa"
itemLabel="#{itemRpa.nmPescador.concat(' ').concat(itemRpa.nmPaterno).concat(' ').concat(itemRpa.nmMaterno)}"
itemValue="#{itemRpa}"
completeMethod="#{correccionROBean.filtrarRpa}"
minQueryLength="4"
maxResults="10"
forceSelection="true">
<p:ajax event="itemSelect" listener="#{correccionROBean.onRpaSelect}" update="rpaAutoComplete"/>
</p:autoComplete>
Here, when I select one item, the listener method is not triggered. When I try to debug the method, it's like the method is not called at all.
Finally, when I push the save button without selecting an item in the <p:autoComplete>, then and only then, the action listener method in the save <p:commandButton> is triggered.
What may cause this behaviour?
Thanks in advance.
EDIT
I added the field immediate="true" to the autocomplete component and that triggered the ajax submit method, but still cannot execute the save button action listener method
SOLVED.
Refeer to Melloware's answer and my reply to that answer for more details.
For those that are unfamiliar with Converters:
The interface Converter, defined in JSF's API, allows to convert the data inputted and outputted to a Auto Complete component (and some other JSF UI components as well and their sub-classes). This interface has two methods:
public Object getAsObject(FacesContext context, UIComponent component, String value): This method must return an Object that is instance of the same class as the value defined in the value field of the Auto Complete component (in my case, it returns a SiepRpaPescador object). You must handle exceptions in this method as it is called automatiquely in two situations:
When you input characters in the Auto Complete text field and the number of inputted characters are equal or greater than the value defined in the minQueryLength field of the Auto Complete component or it's default value if not specified (in my case, when I input 4 characters or more). In this case, the value parameter in this method will be the String you inputted. Notice that if you enabled dropdown (dropdown="true")as in my case and you push the dropdown button, this method is NOT called.
When you submit the form. In this case, the value will be the value of the labelValue field in the Auto Complete component (in my case, #{itemRpa.nrFolio}) converted to String using the toString method defined in the class that value is instance of (#{itemRpa.nrFolio} is an Integer, so the value will be converted using the Integer class' own implementation of toString()) or in the Object class if no implementation of toString() is defined.
public String getAsString(FacesContext context, UIComponent component, Object value): This method must return a String representation of the label value of each item to be displayed in the Auto Complete component. The parameter value is an instance of the same class as the value defined in the labelValue field of the Auto Complete component. This method is called automatiquely when the items are displayed (it doesn't matter if you inputted characters in the Auto Complete's text field or pressed the dropdown button if present) and it's called as many times as defined in the field maxResults (in my case, 10) in the Auto Complete, using the objects obtained from the returned list of the completeMethod (in my case, from each object in the list obtained from #{correccionROBean.filtrarRpa}, this method obtains it's nrFolio, as I stablished in the labelValue field of the AutoComplete).
I hope this helps to you all
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.
Does anyone have a solution for such a problem:
In my app I'm using a complex, programmatically build dashboard based on the primefaces dashboard. To overcome problems with nonunique id's of the panels building the dashboard, I'm binding this component to a request-scoped bean. I'd also like to rebuild the dashboard based on some changable parameters after clicking a commandButton.
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired (in the Invoke Application phase). So, although the dashboard is rebuild eventually, it's not beeing refreshed in the rendered response.
On the other hand, if I try to set immediate attribute of the button to true, the actionListener is fired in the Apply Request Values phase, but still after the getter. Than the lifecycle goes directly to the Render Response phase, and the outcome is the same.
Anyone?
Thank you for the answer. Let me add a bit detail to my problem.
I store a model of a sports tournament as a property of a session scoped bean. It goes like this: the bean has a property "tournament". This class has a list of groups, each with it's table of matches. The idea was to use three different programmatically built components as renderers of this tournament model.
The dashboard would be used for drag-and-drop edition of contestant placement in groups. For viewing match tables and editing their matches I use a tab panel, with panel grid for every table. Finally, I use a panel grid to show a tournament tree. Every of those three components render some part of the model for the user to edit.
Since the model (and therefore those rendering components) are dynamically build depanding on chosable parameters like number of groups for example, i had a problem with id uniqnes when binding them to a session-scoped bean. So I bound them to a request scoped bean. With every request changing the model (mostly ajax) I wanted to rerender those components depending on the parameters set by the user (also stored in the session scoped bean).
The problem is, that when I rebuild the model in the invoke application phase (in a action listener fired by the "rebuild-my-model" button), the components bound to a request-scoped bean have already been "get-ed" from the bean (or so it seems), and they do not refresh on the page.
I would be very gratefull for a clue to what i'm doing wrong, and perhaps a suggestion, if the approach mentioned above is completelly stupid :)
The problem is, that the getter for the dashboard is fired in the Apply Request Values phase, way before the actionListener of the commandButton is fired
I'm not sure why exactly that forms a problem for you. Perhaps you're incorrectly doing business logic in the getter method instead of in the action listener method? Or perhaps you're manually creating the component instead of referencing the JSF-created one and thus always overridding the one in the JSF view?
A proper JSF getter method basically look like this:
public UIComponent getDashboard() {
return dashboard;
}
It should not contain any other line of code. The same applies to the setter method by the way. Any actions wherein you need to manipulate the component's children needs to be done in an action(listener) method, not in a getter/setter method.
I have two input components on my page. Each of them has a converter (It's a converter which checks for empty values, like JSF required one, but for some reasons I cannot use jsf one so I've made my own converter).
I also have a ice:selectBooleanCheckbox:
<ice:selectBooleanCheckbox
styleClass="graUserAppUserGroupAddChk"
value="#{userGroupTableNewRecordBean.addNewDomain}"
partialSubmit="true"
immediate="true"
valueChangeListener="#{userGroupTableNewRecordBean.addDomainListener}"></ice:selectBooleanCheckbox>
As you see I put immediate=true attribute on it, becase when I select this checkbox I do want the conversion phase to be skipped but it does not work, the converters still show their warnings. Do you know why?
I also add a valueChangeListener on this checkbox and called there the renderResponse directly, based on this quote:
So in the value changed listener method for the dropdown lists, just
call renderResponse() from the
FacesContext object and validation and
conversion is bypassed and you can
still do what you want.
public void addDomainListener(final ValueChangeEvent valueChangeEvent) {
// skip validation
logger.info("listener calleddddddddddddd");
FacesContext.getCurrentInstance().renderResponse();
}
Maybe a JSF guru can help?
Thanks a lot...
UPDATE: I know that a solution would be to put the checkbox in a separate form but I cannot afford this...
UPDATE 2: I've corrected some code about listener, so now it is called when clicked but still the converter fails and render response phase is not done...
UPDATE 3: This is not an icefaces issue... I've tried with a h:selectBooleanCheckbox and it happens the same...
The whole question and the functional requirement behind this all is pretty confusing. Why are you using a converter instead of a validator to validate the inputs? Why are you using a converter/validator if you don't seem to care about the conversion/validation outcome?
As you see I put immediate=true attribute on it, becase when I select this checkbox I do want the conversion phase to be skipped but it does not work, the converters still show their warnings.
Putting the immediate="true" on input components does not skip conversion/validation. They just shifts conversion/validation to an earlier phase (i.e. it takes place in apply request values phase instead of validations phase). You basically need to remove immediate="true" from those inputs and put it on the command link/button in order to skip conversion/validation of those inputs. See also Debug JSF lifecycle:
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.
Solved it finally...
I post here the sum up of the question and the solution.
I had a checkbox in my popup. When I select it I want to show some hidden fields but this did not work because I also had two required fields on the same page so jsf PROCESS_VALIDATIONS phase came up...
I thought that putting immediate=true will solve this, but it did not...
So, in my ValueChangeListener of the checkbox I had to manually skip the jsf validation phase:
public void addDomainListener(final ValueChangeEvent valueChangeEvent) {
// skip validation
final PhaseId phaseId = valueChangeEvent.getPhaseId();
final Boolean newValue = (Boolean) valueChangeEvent.getNewValue();
if (phaseId.equals(PhaseId.ANY_PHASE)) {
valueChangeEvent.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
valueChangeEvent.queue();
this.addNewDomain = newValue;
FacesContext.getCurrentInstance().renderResponse();
}
}
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.