Skip to content

Commit 7981dd9

Browse files
committed
new example ! multi step forms
1 parent 0dfca98 commit 7981dd9

File tree

17 files changed

+225
-0
lines changed

17 files changed

+225
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Forms with multiple steps
2+
3+
Multi-steps forms are forms where the user has to go through multiple pages
4+
to fill in all the information.
5+
They are a good practice to improve the user experience
6+
on complex forms by removing the cognitive load of filling in a long form at once.
7+
Additionally, they allow you to validate the input at each step,
8+
and create dynamic forms, where the next step depends on the user's input.
9+
10+
There are multiple ways to create forms with multiple steps in SQLPage,
11+
which vary in the way the state of the partially filled form
12+
is persisted between steps.
13+
14+
This example illustrates the main ones.
15+
All the examples will implement the same simple form:
16+
a form that asks for a person's name, email, and age.
17+
18+
## Storing the state in the database
19+
20+
You can store the state of the partially filled form in the database,
21+
either in the final table where you want to store the data,
22+
or in a dedicated table that will be used to store only partial data,
23+
allowing you to have more relaxed column constraints in the partially filled data.
24+
25+
- **advantages**
26+
- the website administrator can access user inputs before they submit the final form
27+
- the user can start filling the form on one device, and continue on another one.
28+
- the user can have multiple partially filled forms in flight at the same time.
29+
- **disadvantages**
30+
- the website administrator needs to manage a dedicated table for the form state
31+
- old partially filled forms may pile up in the database
32+
33+
## Storing the state in cookies
34+
35+
You can store each answer of the user in a cookie,
36+
using the
37+
[`cookie` component](https://sql.datapage.app/component.sql?component=cookie#component).
38+
and retrieve it on the next step using the
39+
[`sqlpage.cookie` function](https://sql.datapage.app/functions.sql?function=cookie#function).
40+
41+
- **advantages**
42+
- simple to implement
43+
- if the user leaves the form before submitting it, and returns to it later,
44+
the state will be persisted.
45+
- works even if some of the steps do not use the form component.
46+
- **disadvantages**
47+
- the entire state is re-sent to the server on each step
48+
- the user needs to have cookies enabled to fill in the form
49+
- if the user leaves the form before submitting it, the form state will keep being sent to all the pages he visits until he submits the form.
50+
51+
## Storing the state in hidden fields
52+
53+
You can store the state of the partially filled form in hidden fields,
54+
using `'hidden' as type` in the [form component](https://sql.datapage.app/component.sql?component=form#component).
55+
56+
- **advantages**
57+
- simple to implement
58+
- the form state is not sent to the server when the user navigates to other pages
59+
- **disadvantages**
60+
- the entire state is re-sent to the server on each step
61+
- you need to reference all the previous answers in each step
62+
- no *backwards navigation*: the user has to fill in the steps in order. If they go back to a previous step, you cannot prefill the form with the previous answers, or save the data they have already entered.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
insert into users (
2+
name, email, age
3+
) values (
4+
sqlpage.cookie('name'),
5+
sqlpage.cookie('email'),
6+
:age -- This is the age that was submitted from the form in step_3.sql
7+
);
8+
9+
-- remove cookies
10+
with t(name) as (values ('name'), ('email'), ('age'))
11+
select 'cookie' as component, name, '/cookies/' as path, true as remove from t;
12+
13+
select
14+
'alert' as component,
15+
'Welcome, ' || name || '!' as title,
16+
'You are user #' || id || '. [Create a new user](step_1.sql)' as description_md
17+
from users where id = last_insert_rowid();
18+
19+
select 'list' as component, 'Existing users' as title, 'users' as value;
20+
select name as title, email as description from users;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
select
2+
'form' as component,
3+
'step_2.sql' as action;
4+
5+
select
6+
'name' as name,
7+
true as required,
8+
sqlpage.cookie ('name') as value;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
select
2+
'cookie' as component,
3+
'name' as name,
4+
:name as value,
5+
'/cookies/' as path; -- Only send the cookie for pages in the /cookies/ directory
6+
7+
select
8+
'form' as component,
9+
'step_3.sql' as action;
10+
11+
select
12+
'email' as name,
13+
'email' as type,
14+
true as required,
15+
sqlpage.cookie ('email') as value,
16+
'[email protected]' as placeholder,
17+
'Hey ' || coalesce(:name, sqlpage.cookie('name')) || '! what is your email?' as description;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
select
2+
'cookie' as component,
3+
'email' as name,
4+
:email as value,
5+
'/cookies/' as path;
6+
7+
select
8+
'form' as component,
9+
'finish.sql' as action;
10+
11+
select
12+
'age' as name,
13+
'number' as type,
14+
true as required,
15+
'How old are you, ' || sqlpage.cookie('name') || '?' as description;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
update partially_filled_users set age = :age
2+
where :age is not null and id = $id;
3+
4+
insert into users (name, email, age)
5+
select name, email, age from partially_filled_users where id = $id;
6+
7+
delete from partially_filled_users where id = $id;
8+
9+
select
10+
'alert' as component,
11+
'Welcome, ' || name || '!' as title,
12+
'You are user #' || id || '. [Create a new user](index.sql)' as description_md
13+
from users where id = last_insert_rowid();
14+
15+
select 'list' as component, 'Existing users' as title, 'users' as value;
16+
select name as title, email as description from users;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- create a new empty partially_filled_users row, returning its id
2+
insert into partially_filled_users default values
3+
returning
4+
'redirect' as component,
5+
'step_1.sql?id=' || id as link;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
select 'form' as component, 'step_2.sql?id=' || $id as action;
2+
3+
select 'name' as name, true as required, name as value
4+
from partially_filled_users where id = $id;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
update partially_filled_users set name = :name
2+
where :name is not null and id = $id;
3+
4+
select 'form' as component, 'step_3.sql?id=' || $id as action;
5+
6+
select 'email' as name, 'email' as type, true as required, email as value,
7+
'[email protected]' as placeholder,
8+
'Hey ' || name || '! what is your email?' as description
9+
from partially_filled_users where id = $id;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
update partially_filled_users set email = :email
2+
where :email is not null and id = $id;
3+
4+
select 'form' as component, 'finish.sql?id=' || $id as action;
5+
6+
select 'age' as name, 'number' as type, true as required, age as value,
7+
'How old are you, ' || name || '?' as description
8+
from partially_filled_users where id = $id;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
insert into users (name, email, age) values (:name, :email, :age)
2+
returning
3+
'alert' as component,
4+
'Welcome, ' || name || '!' as title,
5+
'You are user #' || id || '. [Create a new user](step_1.sql)' as description_md;
6+
7+
select 'list' as component, 'Existing users' as title, 'users' as value;
8+
select name as title, email as description from users;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
select
2+
'form' as component,
3+
'step_2.sql' as action;
4+
5+
select
6+
'name' as name,
7+
true as required;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
select
2+
'form' as component,
3+
'step_3.sql' as action;
4+
5+
select
6+
'email' as name,
7+
'email' as type,
8+
true as required,
9+
'[email protected]' as placeholder,
10+
'Hey ' || :name || '! what is your email?' as description;
11+
12+
with previous_answers(name, value) as (values ('name', :name))
13+
select 'hidden' as type, name, value from previous_answers;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
select
2+
'form' as component,
3+
'finish.sql' as action;
4+
5+
select
6+
'age' as name,
7+
'number' as type,
8+
true as required,
9+
'How old are you, ' || :name || '?' as description;
10+
11+
with previous_answers(name, value) as (values ('name', :name), ('email', :email))
12+
select 'hidden' as type, name, value from previous_answers;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
select 'list' as component, 'Forms with multiple steps' as title;
2+
3+
select 'Database persistence' as title, 'database' as link;
4+
select 'Cookies' as title, 'cookies/step_1.sql' as link;
5+
select 'Hidden fields' as title, 'hidden/step_1.sql' as link;
6+
7+
select 'text' as component, sqlpage.read_file_as_text('README.md') as contents_md;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- Simple SQLite users table
2+
create table users (
3+
id integer primary key autoincrement,
4+
name text not null,
5+
email text not null,
6+
age integer not null check(age > 0)
7+
);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- this table will store partially filled user forms
2+
create table partially_filled_users (
3+
id integer primary key autoincrement,
4+
name text null, -- all fields are nullable, because the user may not have filled them yet
5+
email text null,
6+
age integer null check(age > 0)
7+
);

0 commit comments

Comments
 (0)