Why is f:event postValidation triggered while submitting another form on the same page - jsf

I have a jsf 2.2 application (myfaces 2.2.8). On a page I have multiple forms from different included (jsf:include) facelet files.
In one file a form is defined with a <f:event type="postValidate"...> tag. In another included file another form is defined with only a submit button.
Clicking on this button triggers the listener defined in f:event. Why?

The f:event tag isn't bound to any of the forms. It's just a tag to tell JSF to invoke a listener if an event of the declared type happens, no matter where in the view. So it's the expected behaviour to be invoked when any of the forms is submitted. You could anyway grab the source form into the listener:
public void listener(ComponentSystemEvent evt) {
//Get the source form
evt.getSource();
}
See also:
JSF f:event documentation
List of JSF 2 events

Related

ValueChangeEvents being fired only after other components are clicked

I'm trying to use an InputFile within JSF (1.1.7) and Apache Trinidad (1.0.11). I define a change event for it but the event is not being fired when I change the file selection but when I click on another component of the form.
Here is the jsp code:
<trh:body>
<tr:panelPage>
<tr:form usesUpload="true" id="myForm">
<tr:inputFile columns="80" id="archivo"
valueChangeListener="#{myBean.changeInputFile}"
immediate="true">
</tr:inputFile>
<tr:commandButton text="Begin"/>
</tr:form>
</tr:panelPage>
</trh:body>
Here is the relevant part of the bean:
public void changeInputFile(ValueChangeEvent event) {
UploadedFile f = (UploadedFile)event.getNewValue();
}
The code only enters into the myBean.changeInputFile method when I click the Begin button (having changed the file selection previously). I would like it to enter into myBean.changeInputFile when I change the selected file in the inputFile component.
Any idea why could be this happening?
Your expextation is wrong. The valuechangelistener is a server-side action that will fire when something is submitted to the server and effectively has a different value than it did before. It is NOT telling the component to behave like modern ajax (jsf 1.1.7 and its valuechangelistener predate the ajax era). The form value is only submitted to the server when you, well, in 'old' html terms use form submission like pressing a submit button (or use some javascript to trigger that like you would in the old plain html days). And since without pressing a button or the added javascript, nothing is submitted to the server the valuechangelistener will not spontaneously do something.
So the behaviour you see is exactly as it should be.

RequestContext sends response but the page doesn't change

I have a JSF page, with some components rendered if a certain value is selected in SelectOneMenu. For that I change their rendered value and call RequestContext.getCurrentInstance().update("#form").
From the client point of view, whenever I select the value, I get a response from server:
<update id="mainForm:addUser:menu_14:menu">
<...some updated values...>
</update>
Yet, the element with id mainForm:addUser:menu_14:menu did not update.
Can anybody tell me what is wrong?
Update
I can add commandButton with update="#form", and pressing this button actually redraws the form as needed. But I need to do this from the backing bean, so...
From the docs:
public abstract void update(String name)
Update a component with ajax.
name - Client side identifier of the component.
So you can't use selectors like you do from the xhtml file, you have to give client ID of the component.
RequestContext.getCurrentInstance().update("mainForm")
How to programmatically ajax-update specific component in backing bean
Are you using Primefaces? You should pass client id to RequestContext.update method. #form won't work. Try update(mainForm).

How to reset form to last loaded values from another form?

My JSF has two forms. Form1 is the main form and it is loaded with existing DB values when the page is loaded. Occasionally, as defined by the business logic, an update submission of Form1 will trigger a PrimeFaces p:dialog, which contains Form2 that collects extra data to complement Form1. If the user provides data that passes validation, the submit h:commandButton in Form2 will invoke a backing bean method that will save the data from both forms. However, if the user cancels the submit button or just closes the the p:dialog, I would like to roll back the state of the view to the last loaded values from the DB.
I have no preference whether to do it by using the PrimeFaces RequestContext from the backing bean in a method that is called by the cancel button or by doing it all in the JSF using either JSF EL or f:ajax. How can this be done?
E.g. RequestContext has a method reset(Collection<String> expressions) but I would like to not be specifying each form field to be reset, instead do all of them.

ActionListener phases in JSF

HI,
I have a doubt on calling the ActionListener method in the JSF beans. For example every request or submission of JSF form is gone through the life cycle of six phases. But, when we are triggering the particular event like action listener or value change listener, is there any lifecycle associated with that request?
Please clarify me.
Any action listener is invoked during invoke action phase, before the real action method. Which action listener methods are to be invoked are determined based on the actionListener attribute of the UICommand component which is associated with the submit.
Any value change listener is invoked during validations phase (or apply request values phase when immediate="true" for the particular UIInput component) after a succesful conversion/validation of the submitted value and only when the submitted value differs from the initial value. Which value change listener methods are to be invoked are determined based on the valueChangeListener attribute of the UIInput components which are associated with the submit.
And no, they do not have their own lifecycle. When they finish executing and return, it's still inside the same phase of the lifecycle. After invoking the valueChangeListener, JSF will continue with conversion/validation of the next UIInput component, or if there are none, then proceed to the next phase. After invoking the actionListener, JSF will continue with the next actionListener or if there are none, invoke the real action method.
Update: after reading your comments again, I think that I now see your doubt about particularly the value change listener. You seem to think that it by default immediately fires a brand new request to the server side during the client side change event. It does that not by default. You can only achieve this by adding a little piece of JavaScript code which submits the entire HTML form during the change event of the HTML input field.
onchange="this.form.submit()"
This part has nothing to do with JSF. It's a simple HTML attribute. Open the page in webbrowser, rightclick and choose View Source. You'll see that it's there. Disable JavaScript in your browser or remove it in JSF code and you'll see that it won't work anymore. You would need to press the submit button yourself to get it all to run.

Problem With JSF 1.1 and PopUp

I am trying to popup a window when someone clicks a button on the data table.
<h:commandButton
action="#{cacheController.popupDetails}"
immediate="false"
onclick="popup()"
value="View Details"
styleClass="submit">
</h:commandButton>
The associated popup function is
function popup() {
window.open('RDDetails.jsf','popupWindow', 'dependent=yes, menubar=no, toolbar=no, height=500, width=400');
}
Now in the new 'RDDetails.jsf" file, I am trying to access the same managedBean cacheController. But the problem is, the pop-up window and JSF lifecycle is not in sync. As a result, the popup first displays blank and when I refresh, it pulls out the proper data.
Is there anyway I can click on a button which will do some processing in the managed bean and then opens a pop up which rerieves the processed data from the managed bean.
I am using JSF 1.1.
You're here basically firing two independent requests: one associated with the form submit and other which opens the RDDetails.jsf in a popup. You'll need to combine this in one request. You can achieve this in basically two ways:
Get rid of the onclick and just add target="_blank" to the <h:form> so that it get submitted into a new window/tab.
Block the default action by adding return false; to the onclick and do the business logic in the constructor of the bean associated with RDDetails.jsf. The only (major) caveat is here that the model won't be updated with the form fields. Thus, you'll need to pass the form fields as request parameters of the popup URL manually with help of JavaScript. You can then make use of managed property entries in the faces-config.xml to inject the GET request parameters into the model.
First way is obviously the easiest, but this doesn't give you a "fullworthy" popup/modal dialog. The second way is a bit harder (unless you've already a good grasp on both JavaScript and JSF). I would then consider to look for a component library which provides a ready-to-use popup component.
See my example:
<h:commandLink action="#{controller.myAction}" onmousedown="document.forms['idform'].target='_blank';">
I'm using jsf 1.1

Resources