I'm trying to understand the best options for pulling off a wizard form in ruby on rails. Ideally I'd like to have it so the application signup has a back and next button that allows the user to submit data in steps.
So in step 1 they could fill out contact info. Once they are done they could click next and be on step 2 to fill out payment info, etc. If they make a mistake, they can click back and correct it. Some steps will be required, while others will not, but you do have to make it to the last step to submit the data to the database to sign up. They then need the ability to go back and fill out the past steps in the same fashion after completion. (example: perhaps if they clicked on a profile link they could recomplete the steps in the same fashion because they didn't want to complete all the steps right away. Maybe by being given a skip button before they completed the steps to sign up?). I also need validation to happen on what steps have been completed preventing them from moving onto the next step until corrected or completed.
Option 1) I've noticed that ajax has been recommended as an option in other questions on stackoverflow. The only problem I have with it is that the user would not be able to sign up if javascript was disabled. Ideally I'd like to have it be native to ruby on rails but I'm willing to work with whatever is necessary to get it to work.
You should watch this rails cast episode on multi step forms:
http://railscasts.com/episodes/217-multistep-forms
Be prepared to rewind and watch again. He's very quick!
There are a couple of plugins that provide wizzard construction facilitation in rails.
Acts as Wizard and Wizardly seem the most popular.
The main idea is to:
* create a model in the first step
* then edit it on subsequent steps,
* applying partial validation on each step and
* having the model implement some sort of state machine.
Wicked looks promising for rails 3:
https://github.com/schneems/wicked
Have a look at wicked, explained in this rails cast: http://railscasts.com/episodes/346-wizard-forms-with-wicked?autoplay=true
An alternative approach, for simpler multi step forms especially, is to simply show-hide parts of a single form depending on the step, this way you don't hit the database on every step but rather let the user build up his object until he's ready with a valid instance.
Such an approach strongly favors using a form class instead of working with the model directly (http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/) and you need to tweak error message rendering a bit.
Pros: only one db hit, no hassle with persisting invalid instances (not null columns, before_save sanity checks for messed up attributes), no callback hell
Cons: more html sent to user, error message tweaks, requires a well built form class to be elegant and really useful
Related
I'm using struts2-jquery-plugin-3.7.0. I'm looking for a component that can create a workflow by exhibiting (creating) multiple steps in a single form on a page in which the current step is processed partially and display the next step if and only if the current step passes validations.
All the steps must be performed sequentially in a defined order.
For example, in a user registration form, personnel information of a user must be filled up first before filling up her contact information and so on.
If any validation is violated while filling up personnel information then, the next step (to fill up contact information) must not be executed. It should only be executed, if no validation is violated in personnel information.
Currently, I can only see <sj:tabbedpanel> which doesn't seem to fulfill these requirements.
Is there any component that can be used in Struts2 to fulfill these requirements?
Long story short : I'm looking for exactly the same component as provided by PrimeFaces <p:wizard> Anyway, I need to create a workflow in which a single page of activities can be exhibited in different and sequential steps. Is there a handy way that can make it possible?
So you want a plugin-in or component for multi-step form in struts2. Well there is no such implementations now, but you can create one of your own. There are many so examples in google.
This one implementation I found in struts2.
Even this is not a bad option. You need to program the underlying logic :)
CSS3-Jquery
I am working on a web application that involves the user filling out a multi-step form that spans several pages. The form has tabbed navigation across the top (these links do not submit the current page) and a next button at the bottom (which does submit). I am considering several strategies for handling form submission/validation:
one action method and view per form page. When you hit next, it submits the form to the action method for the next page. If there are validation errors, you are redirected back to the previous page:
URL's are descriptive and can be copy-pasted
Only redirects in the error case
Since the redirect does not have the form data, we lose context about the submission which makes it hard to display certain error messages
The same validation logic works for redirecting the user if they try to visit a step in the flow that they aren't ready for yet
one action method and view per form page. When you hit next, it submits the form to the current page action. If there are validation errors, the same view is returned. Otherwise, we redirect to the next page action:
URL's are descriptive and can be copy-pasted
Redirects are very common (not sure if this is bad)
When displaying validation errors, we are in the same request as the form submission so we have full access to the invalid input
Have to pass additional context if we want the ability to, for example, add a "Previous" button which also submits
one action method for ALL pages. URL's contain additional context about the step being submitted (e.g. MyController/MyAction/{step}). The controller message selects which view page to return depending on validation and the current step.
URL's are not descriptive (e. g. if I submit step 1 to go to step 2, then the URL the user sees will be the same regardless of whether page 1 (invalid) or page 2 is returned
No redirects
When displaying validation errors, we are in the same request as the form submission so we have full access to the invalid input
A different method I haven't listed here
I have tried to enumerate what I see as some of the pros and cons of each method, but I would be interested to know:
What are other pros and cons of these methods? Are mine correct? Could some of the cons I've listed be designed around?
Is there a standard approach to this problem which I should be using? If so, why is it the standard approach?
I would highly recommend option 2 with a minor modification. You may want to think about also creating one view model per action/view as well. If you have one model that spans all the pages, validation will occur across ALL properties, meaning that even though the user can only edit part of the model on each screen, they could get validation warnings for properties they can't see. We did this recently in a project and it worked beautifully. You have to do some data manipulation in the back-end to combine everything back together, but it was worth it in the end.
As you said, your URLs would be deep-linkable, which means users can Copy/Paste, and more importantly, they can add the page as a favorite in their browser, allowing them to come back to the same place very easily. In my opinion this makes option 3 obsolete.
You will also benefit from the fact that all of your logic for navigation is occurring in one place. You'll have to store the state of the "wizard" on the client (which page you're currently on) so that your controller knows what to do on submit. You'll want to analyze the state of the wizard and make a decision for where the user needs to go next. If you go with option 1, you won't know where you "came from" and server-validation errors will be difficult to display to the client. This is a beautiful example of the POST - REDIRECT - GET pattern. Each page would have 2 actions, a GET that takes simple ids, and a POST which takes more complex models. Post the server, figure out where to go next, redirect to a GET.
Lastly, consider your previous button simply linking directly to the previous step, instead of submitting the form. Otherwise, the user could potentially get stuck on an invalid step. This happened to us and again, worked very nicely.
Hopefully this was helpful. Good luck!
I am currently using sfDoctrineGuardPlugin and sfDoctrineForkedApplyPlugin for my user management.
This works well for me and users can register/login etc
The problem comes with the registration part. The Profile relation that I have is getting particularly large in terms of fields users are required to fill out on registration.
I was thinking of possibly creating a multistep process, possibly 2 steps.
Step 1 is the main details, such as name, username, password etc
Step 2 is the address and my other fields
I don't want my users to scroll down to fill out 25 fields on a single form
I'm not entirely sure how I'd do this and I cannot find any information regarding carrying out this.
Has anyone ever done this before and If so, could someone point me in the right direction of how I'd do this?
Thanks
I'd create a form class for every step. When processing the submitted form, save the submitted part to the session if validation passes.
In the end you'll have an array of validated values for every step, just compose your model object out of them, and save the object.
Here is a generic way of handling multi-step forms in Symfony:
How to 'validate' a Symfony form in steps - instead of calling $form->isValid()
I have a pretty extensive form on one of my rails sites and I was wondering if its possible to dynamically save the form for every onchange input. What I'm trying to prevent is users taking the time to fill the form out and then lose all their changes because of a connectivity issue or something stupid like that...
Any suggestions? Basically, I don't want the form to have to be submitted at all. I just want the form to save like a preference would in an Mac OS X (no apply or save button it just saves).
using rails 3...thanks!
The strain that would put on your server and DB would be several orders of magnitude higher than a more traditional approach. I also agree with Kyle that I would be very confused about the lack of submit button. At the very least, you'll need to notify users each time data is sent to the server and saved successfully, otherwise they'll have no idea why you aren't asking them to save.
Also, think about all the overhead. With every keystroke the user will have to initiate a connection, send their HTTP headers, cookies, the contents of the form, etc.
Have you considered an autosave feature instead? Maybe save the form every 2 minutes if changes have been made, and then put a submit button on the form as well? I think it would save you a great deal of pain, but get you almost the same benefit.
You could attach an ajax event to each input losing focus that would call the Controllers update method.
Most users would be surprised by this behavior though because it isn't the expected behavior of a web site.
If you use AJAX to call update, then here are a few things that might help: jQuery's serialize() function can help gather the form data into a post request without having to call the forms submit action. Using save(:validate => false) will bypass validation if you are saving drafts and want to skip validation until the final save.
I'd like to ask for a solution. For example we have a page. And I have a link to a another action from this page. I want to have an ability to save the values of entered data on the page.
For instance I go to another page enter data and go back. Like the wizard. But the problem is that we can come to the action from different pages. And it need to save several data types.
Is it understand?
Any suggestions?
I'd like to have common solution....
You could also use TempData to persist data between requests.
In the past for wizards I have used Session to store data as it gets built up along the way.
One thing to not forget is to validate the data you are storing in the session everytime you go to use it. If not a user can exploit the back button to fake certain scenarios. For example:
User uses the wizard and gets to step 3 in the wizard.
They then go to another page that is not part of the wizard.
Then the user enters the wizard again and
only gets to step 2 of the wizard.
User then uses the back button to go all
the way back to the original wizard
that they were on step 3 for.
In this case the data in your session if posted will think it came from the original wizard even though the data in the session is reflecting only up to step 2 from when the user accessed the wizard the second time. Use a unique key each time someone starts a wizard and validate it at each step.
Hope that helps and isn't too confusing (it was a bit to me typing it).
An alternative is to persist the data via the TempData but each time you will need to pull it out and persist it for posting back to the next step. Then rebuild it, add to it and repeat. This can be a lot of work as well but at least you don't have to worry about things happening out of synch.