multi-stage form strategies - jsf

Currently I'm working on building a page for inputting pricing data for different products my company handles. Pricing data is somewhat complicated, and so different forms are needed depending on what item new data is being entered for. Right now my strategy for dealing with this is to split the page into multiple forms, with an AJAX update on the next stage triggered when valid data is entered. Each form contains a ui:include pointed to a method on a controller bean, which returns a string pointing to a xhtml snippet with the appropriate form structure for the previously entered data.
<form id="stageOne"> Some content that triggers an ajax update of stageTwo </form>
<form id="stageTwo"> <ui:include src="#{controller.getStageTwo()"> </form>
And the backing bean method:
public String getStageTwo() {
switch (stageOneContent) {
case 1: return "/context-root/snippetName.xhtml";
case 2: return "/context-root/snippetName2.xhtml";
}
}
This solution feels somehow wrong to me, particularly having the controller method be responsible for knowing the exact location of all the xhtml snippets the calling page might use. I am still relatively new, and feel like I might be missing something. Is there a better way to handle this scenario?

How about just something like this?
<ui:include src="snippetName#{controller.stageOneContent}.xhtml">
You only need to rename snippetName.xhtml to snippetName1.xhtml.

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).

Pure Java/JSF implementation for double submit prevention

We're using JSF 2.0 on WebSphere v8.5 with several component libraries PrimeFaces 4.0, Tomahawk 2.0, RichFaces, etc.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed, or when the submit button is clicked once again. I have many applications with different scenarios.
For now I have considered disabling the button with a piece of JavaScript in onclick attribute, but this is not satisfying. I'm looking for a pure Java implementation for this purpose, something like the Struts2 <s:token>.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed
For that there are at least 2 solutions which can not be combined:
Perform a redirect after synchronous post. This way the refresh would only re-execute the redirected GET request instead of the initial request. Disadvantage: you can't make use of the request scope anymore to provide any feedback to the enduser. JSF 2.0 has solved this by offering the new flash scope. See also How to show faces message in the redirected page.
Perform the POST asynchronously in the background (using ajax). This way the refresh would only re-execute the initial GET request which opened the form. You only need to make sure that those forms are initially opened by a GET request only, i.e. you should never perform page-to-page navigation by POST (which is at its own already a bad design anyway). See also When should I use h:outputLink instead of h:commandLink?
or when the submit button is clicked once again
For that there are basically also at least 2 solutions, which could if necessary be combined:
Just block the enduser from being able to press the submit button during the submit and/or after successful submit. There are various ways for this, all depending on the concrete functional and design requirements. You can use JavaScript to disable the button during submit. You can use JSF's disabled or rendered attributes to disable or hide the button after submit. See also How to do double-click prevention in JSF 2. You can also use an overlay window during processing ajax requests to block any enduser interaction. PrimeFaces has <p:blockUI> for the purpose.
Validate uniqueness of the newly added entity in the server side. This is way much more robust if you absolutely want to avoid duplication for technical reasons rather than for functional reasons. It's fairly simple: put a UNIQUE constraint on the DB column in question. If this constraint is violated, then the DB (and DB interaction framework like JPA) will throw a constraint violation exception. This is best to be done in combination with a custom JSF validator which validates the input beforehand by performing a SELECT on exactly that column and checking if no record is returned. A JSF validator allows you to display the problem in flavor of a friendly faces message. See also among others Validate email format and uniqueness against DB.
Instead of creating a token manually, you can use BalusC' solution. He proposed a Post-Redirect-GET pattern in his blog
Alternative solutions can be found in these answers:
Simple flow management in Post-Redirect-Get pattern
How can Flash scope help in implementing the PostRedirectGet (PRG) pattern in JSF2.0
<!--Tag to show message given by bean class -->
<p:growl id="messages" />
<h:form>
<h:inputText a:placeholder="Enter Parent Organization Id" id="parent_org_id" value="#{orgMaster.parentOrganization}" requiredMessage="Parent org-id is required" />
<h:commandButton style="margin-bottom:8px;margin-top:5px;" class="btn btn-success btn-block " value="Save" type="submit" action="#{orgMaster.save}" onclick="resetform()" />
</h:form>
public String save() {
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getFlash().setKeepMessages(true); //This keeps the message even on reloading of page
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Your submission is successful.", " ")); // To show the message on clicking of submit button
return "organizationMaster?faces-redirect=true"; // to reload the page with resetting of all fields of the form.. here my page name is organizationMaster...you can write the name of form whose firlds you want to reset on submission
}

send bean data from one jsf facelet to another

I have a table in my jsf application with some data from the database. I have made the id values a link, and my goal is to pass the data from the selected row to another facelet. How can I do this? The href I have is:
<td>#{product.id}</td>
So the goal is that when the user clicks the link, the editOrDeletePage is displayed, and I want the editOrDeletePage to "ingest" the product id, so that it knows what data to display? How can I do this?
If you definetely want to use static links, you may, of course, just read a request parameter from a target page using some kind of event listener
<f:event listener="#{bean.preRender}" type="preRenderView" />
And read the parameter from request:
FacesContext facesContext = FacesContext.getCurrentInstance();
String productId = (String) facesContext.getExternalContext().
getRequestParameterMap().get("productid");
But it's not really a JSF way to handle navigation, I belive. You may want to use commandLink or some other way of handling user actions. Or maybe, even better, think of using data table, where a user can choose a row, and you can process selection.

JSF page navigation failing with NullPointerException

I wrote two pages...one a form where data submitted and second just to confirm the transaction actually carried out some calculation.
I have a managed bean i.e. FormDataBean and a class Reservation.java from which i instantiate for each booking made. Now I have at the end of a form a submit button:
<h:commandButton value="Submit" action="confirmation"/>
in the bean I have setters and getters as usual. in a method i defined I create an instance of Reservation, then set the beans variables to the instance variabels, like
reservation.startDate = startDate;
reservation.endDate = endDate;
reservation.checkRange();
The last method, i.e. checkRange() will use the assigned values to instance variables to carry calculation. it should return a string successful or failure.
Now when I enter data in the form, and press submit, it just refreshes the page but nothing is submitted. because it doesn't go to next page :(
Any idea what is happening? I don't need to define a navigation rule, because in other project, I carry out simple calculation and display result in next page and it worsks! Please advice
Thanks,
Your are missing to tell us some of the more important details so the answer is a kind of guesswork.
As you don't use navigation rules I assume you are using JSF 2, aren't you?
With JSF 2 you can directly set the new navigation target, without navigation rules. A forward to "confirmation" should work if your outcome file is named confirmation.xhtml. Check that. With a navigation rule you could forward it do a different file.
This part should work regardless of the rest.
For the bean not getting any values make sure that you are using the correct scope either through annotation or entry in your faces-config.xml. As you have a quite unusal validation mechanism you probably have to use the session scope.
The correct way would be using an actionlistener that does your checks and then sets the navigation depending on your checks. The bean scope could be more restrictive then.
Did you try action="confirmation?faces-redirect=true"?

Wicket : Can a Panel or Component react on a form submit without any boilerplate code?

I am currently evaluating Wicket and I am trying to figure out how things work.
I have a question regarding form submit and panels (or other components).
Imagine a custom wicket panel which contains a text field, doing as-you-type validation using ajax. This panel is added to a form.
How can the Panel react a form submit (let's say because javascript/ajax is unavailable)?
I am currently only aware of one solution: calling a panel's method inside the Form onSubmit() method. But this seems not like a "reusable" approach here, because I have to add boilerplate code to every form's onSubmit() which contains the panel (and every developer which use the panel must know this).
So here comes my question: Is there any way that a Panel/Component can "detect" a form submit in some way? Or is there any other solution beside this?
Thank you.
Make your panels implement org.apache.wicket.markup.html.form.IFormModelUpdateListener, and the updateModel() method should be called when the containing form is submitted and passes validation.
There's a good example of code using this by one of the wicket authors at the Wicket In Action blog.
Well, you could simply do the following:
Panel{
Form{
onSubmit(){
Panel.this.onSubmit();
}
}
protected void onSubmit(){}
}
...
This means that any panel that extends your panel need only override the onSubmit and the form no matter what it is in html will call that method. That way you can extend the panel and only override one method for each form.
With regard to form components, the framework handles it for you transparently. Forms are aware of any child form components, even if they haven't been added directly to the parent form.
I would have a Form inside that Panel. This way, you can reuse that Panel without requiring an external Form. As Forms can not be nested inside each other in HTML, Wicket will swap the inner Form(s) into 's transparently, but will make sure that each of the inner Forms takes part of the form processing (validation,..).
You can override the OnSubmit() function of the Form in your Panel. Wicket will call it for you.
what do you mean by "react"? I have only started recently with Wicket, but FWIK, form submit updates the model of a component, and then it calls onSubmit(), which you can override to take special actions beyond that. See Wicket in Action, chapter 6.
After that, the page (and it's components) get re-rendered, using the updated model, so basically, they really "react" on a submit, with quite few lines of code.
For your mentioned case with Component in a Form, have a look at the CompoundPropertyModel.
Implementing IFormSubmitListner and IFormModelUpdateListener shall call the respective methods during a form submit.
However, if you want to do some processing after form submit, I'm afraid you have no choice but to write some boilerplate code yourself.

Resources