Show each error on its field
Task: refuse a bad form and say, next to each field, what is wrong with it.
yaml
# Recipe: the rules live on the action; the form shows each refusal on its field.
paths:
components: ./components
migrations: ./migrations
datasources:
db:
driver: sqlite
database: ./data/guests.dbsql
CREATE TABLE guests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL,
age INTEGER NOT NULL
);The rules are written once, on the action's q:params. The ui:form reads them and puts them on its fields (required, minlength, type="number", min...), so the browser checks first. The server checks again, every field at once: when one fails, the action does not run, the page comes back and each field shows its own message.
xml
<q:component name="Guests">
<!-- The rules are written once, on the action. The form reads them (UI-9)
and the server checks them again (ACT-2), every field at once. -->
<q:action name="register" method="POST">
<q:param name="name" required="true" minlength="2" maxlength="60" />
<q:param name="email" type="email" required="true" />
<q:param name="age" type="integer" required="true" min="18" max="120" />
<q:query name="added" datasource="db">
INSERT INTO guests (name, email, age) VALUES (:name, :email, :age)
<q:param name="name" value="{name}" type="string" />
<q:param name="email" value="{email}" type="string" />
<q:param name="age" value="{age}" type="integer" />
</q:query>
<q:redirect url="/" flash="{name} is on the list." />
</q:action>
<ui:window title="Guest list">
<q:if condition="flash">
<ui:alert variant="{flashType == 'error' and 'danger' or 'success'}">{flash}</ui:alert>
</q:if>
<ui:form on-submit="register">
<ui:formitem label="Name"><ui:input bind="name" /></ui:formitem>
<ui:formitem label="E-mail"><ui:input bind="email" /></ui:formitem>
<ui:formitem label="Age"><ui:input bind="age" /></ui:formitem>
<ui:button variant="primary">Add guest</ui:button>
</ui:form>
</ui:window>
</q:component>error="field" in a test checks that the field was refused, and message= the text shown next to it:
xml
<q:test name="a valid guest is added" page="/">
<test:submit action="register" name="Ana" email="ana@example.com" age="30" />
<test:expect redirect="/" flash="Ana is on the list." />
<test:expect table="guests" count="1" where="name = 'Ana' AND age = 30" />
</q:test>
<q:test name="every broken field gets its own message" page="/">
<test:submit action="register" name="A" email="not an address" age="12" />
<test:expect redirect="/" />
<test:expect error="name" message="Must be at least 2 characters" />
<test:expect error="email" message="Must be a valid email" />
<test:expect error="age" message="Must be at least 18 (got 12)" />
<test:expect text="Must be at least 2 characters" />
<test:expect table="guests" count="0" />
</q:test>
<q:test name="a missing field is refused as Required" page="/">
<test:submit action="register" name="Ana" email="ana@example.com" />
<test:expect error="age" message="Required" />
<test:expect table="guests" count="0" />
</q:test>text
tests/guests.test.q
PASS a valid guest is added
PASS every broken field gets its own message
PASS a missing field is refused as Required
3 passed, 0 failed