Skip to content

Commit a39f9d0

Browse files
committed
add an example for forms with a variable number of fields
See #38
1 parent 9c781dc commit a39f9d0

File tree

11 files changed

+150
-0
lines changed

11 files changed

+150
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Handling forms with a variable number of fields
2+
3+
This example shows how to handle forms with a number of fields
4+
that is not known in advance, but depends on the contents of the database.
5+
6+
## The model
7+
8+
We have a database with a table
9+
`products` that contains the products,
10+
a table `orders` that contains the orders,
11+
and a table `order_items` that contains the items of each order.
12+
13+
We want to display a form to create a new order, with a field for each product.
14+
15+
We cannot know in advance how many products there are,
16+
so we cannot write a simple insert statement for `orders_items`,
17+
like
18+
19+
```sql
20+
INSERT INTO order_items (product_id, quantity)
21+
VALUES (:product_1, :product_1_quantity);
22+
```
23+
24+
Instead, we use a single POST variable of type array to store the
25+
product IDs and quantities, like so:
26+
27+
```sql
28+
SELECT
29+
'product_quantity[]' AS name,
30+
'Quantity of ' || name AS label
31+
FROM products
32+
```
33+
34+
And then we parse the array in SQLite with the [JSON_EACH](https://www.sqlite.org/json1.html#jeach) function.
35+
36+
## Screenshots
37+
38+
![](./screenshots/home.png)
39+
![](./screenshots/order-form.png)
40+
![](./screenshots/order.png)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
SELECT 'shell' AS component, 'Products' AS title;
2+
3+
SELECT 'list' AS component, 'Products' AS title;
4+
SELECT 'Add a new product' AS title,
5+
'red' AS color,
6+
'new_product_form.sql' AS link,
7+
TRUE AS active;
8+
SELECT 'Pass an order' AS title,
9+
'blue' AS color,
10+
'order_form.sql' AS link,
11+
TRUE AS active;
12+
SELECT
13+
name AS title,
14+
price || '' AS description
15+
FROM products;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
SELECT 'shell' AS component, 'New product' AS title;
2+
3+
SELECT 'form' as component,
4+
'New product' as title,
5+
'Create product' as validate,
6+
'new_product_insert.sql' as action;
7+
SELECT 'Name' as name;
8+
SELECT 'Price' as name, 'number' as type;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
INSERT INTO products (name, price)
2+
VALUES (:Name, :Price)
3+
RETURNING
4+
'redirect' AS component,
5+
'index.sql' AS link
6+
;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
SELECT 'shell' AS component, 'Order' AS title;
2+
3+
SELECT 'form' as component,
4+
'Pass an order' as title,
5+
'Order' as validate,
6+
'order_insert.sql' as action;
7+
8+
SELECT 'Name' as name, 'Your full name' AS placeholder;
9+
SELECT 'Email' as name, 'Your email address' AS placeholder;
10+
SELECT 'product_quantity[]' AS name,
11+
'Quantity of "' || name || '"' AS label,
12+
'Number of "' || name || '" you wish to order, for ' || price || ' € each.' AS description,
13+
'number' AS type,
14+
1 AS step,
15+
0 as min,
16+
0 as value
17+
FROM products
18+
ORDER BY id;
19+
20+
-- We include the product ids in the form as hidden fields, so that we can use them for the insertion.
21+
SELECT 'product_id[]' AS name, '' AS label, 'hidden' AS type, id as value
22+
FROM products ORDER BY id;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
INSERT INTO orders(customer_name, customer_email)
2+
VALUES (:Name, :Email);
3+
4+
INSERT INTO order_items(order_id, quantity, product_id)
5+
SELECT
6+
last_insert_rowid(), -- The id of the order we just inserted. Requires SQLPage v0.9.0 or later.
7+
CAST(quantity.value AS INTEGER),
8+
CAST(product.value AS INTEGER)
9+
FROM JSON_EACH(:product_quantity) quantity
10+
INNER JOIN JSON_EACH(:product_id) product USING (key)
11+
WHERE CAST(quantity.value AS INTEGER) > 0
12+
RETURNING
13+
'orders.sql?id=' || order_id as link,
14+
'redirect' as component;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
SELECT 'alert' as component,
2+
'Thanks !' as title,
3+
'analyze' as icon,
4+
'teal' as color,
5+
'Your order is being processed. You will head from us soon.' as description;
6+
SELECT 'index.sql' as link,
7+
'Back to homepage' as title;
8+
9+
SELECT 'list' AS component,
10+
'Order summary' AS title;
11+
SELECT
12+
quantity || ' x ' || name AS title,
13+
'Subtotal: ' || quantity || ' x ' || price || ' € = ' || (quantity * price) || '' AS description
14+
FROM order_items
15+
INNER JOIN products ON products.id = order_items.product_id
16+
WHERE order_id = $id;
17+
18+
SELECT
19+
'Total: ' || SUM(quantity * price) || '' AS title,
20+
'red' AS color,
21+
TRUE AS active
22+
FROM order_items
23+
INNER JOIN products ON products.id = order_items.product_id
24+
WHERE order_id = $id;
28.1 KB
Loading
50.8 KB
Loading
38.6 KB
Loading

0 commit comments

Comments
 (0)