# Form tables and choice matrices Collect repeating rows (order lines, expenses, a staff list) or a grid of ratings (satisfaction, agreement) in one HTML file. Submit once to the portal form endpoint. Do not invent a spreadsheet server. Replace `FORM_ENDPOINT` with the portal submit URL from the HTML skill. ## Table vs choice matrix | | **Table** | **Choice matrix** | |---|---|---| | What it is | Spreadsheet-like rows. Each column can be a different field type. | Fixed grid. Rows are statements; columns are the same scale. | | Typical use | Order list, expense breakdown, staff directory, “add another item” | Satisfaction survey, Likert (“Strongly disagree” … “Strongly agree”), CSAT per topic | | Add rows | Yes — respondent can add/remove rows | Usually no — rows are the questions you defined | | Column types | Short text, email, date, dropdown, number | Radio (or equivalent) per cell | Do not treat a matrix as a table of mixed types. Do not treat a table as a rating grid. ## Table: HTML shape Keep every row inside the same `
`. One POST at the end. ```html
Item Qty Notes
``` Also collect `name` and `email` on the form so the portal can attach a lead. On submit, also send a JSON snapshot so the dashboard is readable: ```html ``` ```javascript function serializeTable(table) { const headers = [...table.querySelectorAll("thead th")].map(th => th.textContent.trim()).filter(Boolean); const rows = [...table.querySelectorAll("tbody tr")].map(tr => { const obj = {}; tr.querySelectorAll("input, select, textarea").forEach((el, i) => { obj[headers[i] || el.name] = el.value; }); return obj; }); document.getElementById("table_rows").value = JSON.stringify(rows); } ``` Call `serializeTable` before submit. Number new rows uniquely (`row_2_item`, `row_3_item`, …). Empty rows may be omitted. **Column types allowed:** short text, email, date, dropdown (` ``` Use a unique `name` per row. Values are the scale points. Optional: add a short comment field after the grid. ## Adding to an existing form If the user already has HTML: 1. Do not replace the form. Insert the table or matrix before the submit button. 2. Keep the existing `action`, `name`, and `email` fields. 3. Add `table_rows` (hidden JSON) for tables, or one radio group per matrix row. 4. Keep a single `` and a single submit. ## Submit `POST` `FormData` to `FORM_ENDPOINT`. Do not set `Content-Type`. If `YOUR_FORM_UUID` is still a placeholder, skip the network request and still show thank-you. ## Visual Match the rest of the page. Readable labels, one accent color, no spreadsheet chrome. On mobile, no clipped columns.