Hi. I would like to know the proper organization in Ember for a multi-page user signup form. Here are my requirements:
-
The steps/views/pages of the form should all edit the same model, and possibly even multiple models, that will be submitted to the server via ember-data once the form is completed.
-
Pressing the back/forward buttons in the browser should move the form pages back/forwards.
-
It is not necessary to give each form page its own URL, but if it makes it easier then that’s fine. If the user visits a URL in the middle of the form without first completing the first steps, Ember should redirect to the beginning of the form.
-
The model data should not be passed between form pages via URL GET parameters. Lets keep the URLs somewhat clean.
Should this be implemented with a single route? Multiple routes? How should the models be stored and passed from view to view?
1 Like
If it helps, I’ve considered three possible approaches, but don’t know which one is better practice:
-
Each page in the form gets its own unique route, and all routes share the same parent route/controller. The model(s) are stored in the parent controller and accessed/populated by the child routes.
-
The entire form is stored in one route, with separate components for each step. The controller contains a currentStep
property to keep track of which step it is currently displaying. To get this to work with the browser history, currentStep
is a query parameter that shows up in the URL.
-
The entire form is stored in one route almost identically to option #2, but currentStep
is not a query parameter, and instead some magic code that I don’t know about yet updates the browser history whenever the user navigates to the next/previous step without actually changing the URL.
1 Like
- is not an option. In ember apps you only change the url via routes or query params.
(1) and (2) are both fine approaches to this.
1 Like
Multiple routes and it’s how the checkout flow for https://store.nest.com was implemented. Unfortunately, the pattern wasn’t extracted out into something reusable but it does prove it’s a possibility.
I came across a similar problem some time ago. I solved it like you explained on the first approach:
I have a users/signup.js
route and a users/signup.js
controller. The route returns a new user (i.e. this.store.createRecord('user'))
and the controller has the save()
method.
I also have child routes (take users/signup/username.js
as an example) and their models just return their parent’s model (i.e. return this.modelFor('user.signup')
) and they make use the users/signup
controller.
In the last step, I call the controller’s save()
method.
It meets all the requirements you talked about:
- The steps edit the same model;
- Back/Forward buttons work;
- Each step has its own URL;
- Clean URLs.
2 Likes
Thanks @romulomachado do you have any public repo to see this in action?