Vários formulários numa página
Tradução automática
Esta página foi traduzida automaticamente do inglês e ainda não foi revisada por um falante nativo; correções são bem-vindas no GitHub. Se algo não bater, vale o original em inglês. O código e os resultados são os mesmos do original, importados dos arquivos testados.
Tarefa: acrescentar, remover e esvaziar a partir de uma página, cada um com a sua ação.
# Recipe: several forms on one page, each posting to its own action.
paths:
components: ./components
migrations: ./migrations
datasources:
db:
driver: sqlite
database: ./data/cart.dbCREATE TABLE cart (
id INTEGER PRIMARY KEY AUTOINCREMENT,
item TEXT NOT NULL,
quantity INTEGER NOT NULL
);
INSERT INTO cart (item, quantity) VALUES ('Coffee', 1), ('Bread', 2);Cada ui:form on-submit e cada ui:button on-click envia o nome da sua ação num campo chamado action; a página roda essa ação e nenhuma outra. with="id={cart.id}" envia o id da linha junto com o botão.
<q:component name="Cart">
<!-- Three actions on one page. Each form (and each button) sends the name
of its action in the field "action"; the page runs that one only. -->
<q:action name="add" method="POST">
<q:param name="item" required="true" maxlength="60" />
<q:param name="quantity" type="integer" min="1" max="99" default="1" />
<q:query name="added" datasource="db">
INSERT INTO cart (item, quantity) VALUES (:item, :quantity)
<q:param name="item" value="{item}" type="string" />
<q:param name="quantity" value="{quantity}" type="integer" />
</q:query>
<q:redirect url="/" flash="Added {quantity} × {item}." />
</q:action>
<q:action name="remove" method="POST">
<q:param name="id" type="integer" required="true" />
<q:query name="removed" datasource="db">
DELETE FROM cart WHERE id = :id
<q:param name="id" value="{id}" type="integer" />
</q:query>
<q:redirect url="/" flash="Removed." />
</q:action>
<q:action name="empty" method="POST">
<q:query name="emptied" datasource="db">DELETE FROM cart</q:query>
<q:redirect url="/" flash="The cart is empty." />
</q:action>
<q:query name="cart" datasource="db">
SELECT id, item, quantity FROM cart ORDER BY id
</q:query>
<ui:window title="Cart">
<q:if condition="flash">
<ui:alert variant="{flashType == 'error' and 'danger' or 'success'}">{flash}</ui:alert>
</q:if>
<ui:form on-submit="add">
<ui:hbox gap="sm">
<ui:input bind="item" placeholder="Item" grow="true" />
<ui:input bind="quantity" width="80" />
<ui:button variant="primary">Add</ui:button>
</ui:hbox>
</ui:form>
<q:loop query="cart">
<ui:hbox gap="sm" align="center">
<ui:text>{cart.quantity} × {cart.item}</ui:text>
<!-- with= sends the row's id along with the action's name. -->
<ui:button on-click="remove" with="id={cart.id}">Remove</ui:button>
</ui:hbox>
</q:loop>
<ui:button on-click="empty" variant="danger">Empty the cart</ui:button>
</ui:window>
</q:component>Numa página com mais de uma ação, um envio cujo action falta ou não nomeia nenhuma delas responde 400 e lista as ações que existem. Nada roda no lugar, como o último teste confere:
<q:test name="each form runs its own action" page="/">
<test:submit action="add" item="Milk" quantity="3" />
<test:expect flash="Added 3 × Milk." />
<test:submit action="remove" id="1" />
<test:expect flash="Removed." />
<test:expect table="cart" count="2" />
<test:expect table="cart" count="0" where="item = 'Coffee'" />
</q:test>
<q:test name="the button with no fields empties the cart" page="/">
<test:submit action="empty" />
<test:expect redirect="/" flash="The cart is empty." />
<test:expect table="cart" count="0" />
</q:test>
<q:test name="a post that names no action of the page is refused" page="/">
<test:submit action="checkout" />
<test:expect status="400" />
<test:expect text="No q:action named 'checkout' on this page. Available: add, remove, empty." />
<test:expect table="cart" count="2" />
</q:test>tests/cart.test.q
PASS each form runs its own action
PASS the button with no fields empties the cart
PASS a post that names no action of the page is refused
3 passed, 0 failedVeja ACT-5.