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

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.

Related

How to restore ViewScoped bean when user clicks back button?

Lets say I have a #ViewScoped Bean behind my current page A. Now the user navigates to page B via a normal get request, lets say to www.google.com.
When the user clicks the back button of the browser, I would like to restore the #ViewScope of the previous page, so that it appears exactly as it was left. Is that possible to achieve somehow?
I dont want to make my page A #SessionScoped so that the backing beans do not disturb each others state when opened in two browser tabs.
Since version 2.6 OmniFaces has this feature, is called #ViewScoped(saveInViewState = true) But with some caution!
It's very important that you understand that this setting has potentially a major impact in the size of the JSF view state, certainly when the view scoped bean instance holds "too much" data, such as a collection of entities for a data table, and that such beans will in fact never expire as they are stored entirely in the javax.faces.ViewState hidden input field in the HTML page. Moreover, the #PreDestroy annotated method on such bean will explicitly never be invoked, even not on an unload as it's quite possible to save or cache the page source and re-execute it at a (much) later moment.
A more programmatical solution is the #ConversationScoped. With the convertsation id as parameter can you restore the view.
conversationscope example
Yes it is possible, pass parameter like this using f:param this will pass your parameter to the next screen.
<h:commandLink action="screenName" value="#{search.participantName}">
<f:param value="#{searchcus.participantId}" name="PARTICIPANT_ID"/>
<f:param name="PARENT_SCREEN_CODE" value="SEARCH_PARTICIPANT"/>
</h:commandLink>
After that in init() method get value as a parameter to fetch the result.

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

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

Show dialog after successful operation in jsf?

I am adding some value to database in jsf. I have a manage bean for this purpose. Now when insertion is successful then I want to show a success alert dialog. please tell me how to do it?
I would suggest to add a dialog component in your page (the same page that calls your bean to insert a value into the DB for instance)
p:dialog id="dialog" widgetVar="widgetVarOfDialog"
Then let assume that you have either a commandButton or a commandLink (you don't provide enough information in your first post) that triggers the insert action in your bean. Just add an oncomplete callback:
p:commandButton action="#{bean.insertValue}" oncomplete="PF('widgetVarOfDialog').show()"
You could also display a p:dialog right from your bean method by using:
RequestContext context = RequestContext.getCurrentInstance();
context.execute("PF('widgetVarOfDialog').show()");

#PostConstruct and commandButton/commandLink parameters case

I'm wondering if there is a common pattern for the following scenario.
Let's say I have one JSF page backed with one request scoped bean.
I want to fech all data rows from a database table when a user enters this page.
The same JSF page contains a form to provide query criteria. When the user provides query criteria and submits the form, I want to display the result on the same page, too.
The suitable place to fetch all rows at page entry is the #PostConstruct method. This is a nice place to do that since additional (injected) request parameters are already available here and can be used in the query. However, parameters submited from the form are not available yet. They can be accessed in the action method.
If the user queries the database table using the form criteria the database will be queried twice in this case. The request scoped bean will be recreated and #PostConstruct method fetching all rows will be called prior to the form action method fetching what the user wants.
Of course I could redirect the form result to another JSF page backed by a different bean with DB query only in the action method. But is there a way to accomplish fetching only what is needed with one JSF page and one managed bean?
What you should use is a combination of ViewScoped managed bean and ajax engine. You're right about using #PostConstruct method to fetch all initial rows of your data table. Any further requests from your query form will not trigger this method again. Instead, you only need to make an ajax call to sort out the entries in your data table and update it at the end of the call. It would be something like this:
<h:dataTable id="myTable">
...
</h:dataTable>
<h:form>
...
<h:commandButton actionListener="#{viewScopedBean.sortEntries}">
<f:ajax render="myTable" execute="myForm" />
</h:commandButton>
</h:form>

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