跳到正文

从列表中选择 ​

机器翻译

本页由英文原文机器翻译而来,尚未经过母语审校,欢迎在 GitHub 上提出修改。内容如有出入,以英文原文为准。

任务: 一个从列表中取一个值的字段,以及一个是/否复选框。

yaml
# Recipe: a field that takes one value from a list.
paths:
  components: ./components
  migrations: ./migrations

datasources:
  db:
    driver: sqlite
    database: ./data/orders.db
sql
CREATE TABLE orders (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    size TEXT NOT NULL,
    milk TEXT NOT NULL,
    to_go INTEGER NOT NULL
);

列表只写一次,作为动作的 q:param 上的 enum。没有自己选项的 ui:select 或 ui:radio 会从这里获取选项,服务器会拒绝不在列表中的值。default 补上省略的字段。 复选框只有勾选时才会发送值,所以 type="boolean" default="false" 让它成为 true 或 false。

xml
<q:component name="Coffee">
  <q:action name="order" method="POST">
    <!-- enum is the list: the form's select and radios take their options
         from it (UI-9), and the server refuses anything else (ACT-2). -->
    <q:param name="size" required="true" enum="small,medium,large" />
    <q:param name="milk" enum="none,whole,oat" default="none" />
    <q:param name="to_go" type="boolean" default="false" />
    <q:query name="placed" datasource="db">
      INSERT INTO orders (size, milk, to_go) VALUES (:size, :milk, :to_go)
      <q:param name="size" value="{size}" type="string" />
      <q:param name="milk" value="{milk}" type="string" />
      <q:param name="to_go" value="{to_go}" type="boolean" />
    </q:query>
    <q:redirect url="/" flash="A {size} coffee, milk: {milk}{', to go' if to_go else ''}." />
  </q:action>

  <ui:window title="Order a coffee">
    <q:if condition="flash">
      <ui:alert variant="{flashType == 'error' and 'danger' or 'success'}">{flash}</ui:alert>
    </q:if>
    <ui:form on-submit="order" submit="Order">
      <ui:formitem label="Size"><ui:select bind="size" /></ui:formitem>
      <ui:formitem label="Milk"><ui:radio bind="milk" /></ui:formitem>
      <ui:checkbox bind="to_go" label="To go" />
    </ui:form>
  </ui:window>
</q:component>
xml
<q:test name="the options come from the enum" page="/">
  <test:visit />
  <test:expect text="small" />
  <test:expect text="large" />
  <test:expect text="oat" />
</q:test>

<q:test name="an order with the defaults" page="/">
  <test:submit action="order" size="large" />
  <test:expect redirect="/" flash="A large coffee, milk: none." />
  <test:expect table="orders" count="1" where="size = 'large' AND milk = 'none' AND to_go = 0" />
</q:test>

<q:test name="the box, when sent, is true" page="/">
  <test:submit action="order" size="small" milk="oat" to_go="on" />
  <test:expect flash="A small coffee, milk: oat, to go." />
  <test:expect table="orders" count="1" where="to_go = 1" />
</q:test>

<q:test name="a value outside the list is refused" page="/">
  <test:submit action="order" size="huge" milk="soy" />
  <test:expect error="size" message="Must be one of: small, medium, large" />
  <test:expect error="milk" message="Must be one of: none, whole, oat" />
  <test:expect table="orders" count="0" />
</q:test>
text
tests/order.test.q
  PASS  the options come from the enum
  PASS  an order with the defaults
  PASS  the box, when sent, is true
  PASS  a value outside the list is refused
4 passed, 0 failed

参见 ACT-2 和 UI-9。

MIT 许可证 · 使用 VitePress 构建