Skip to content

A paginated list ​

Task: show 23 posts ten at a time, with links to the other pages.

yaml
# Recipe: a long list, one page at a time, with the links to the others.
paths:
  components: ./components
  migrations: ./migrations

datasources:
  db:
    driver: sqlite
    database: ./data/blog.db
sql
CREATE TABLE posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL
);

-- 23 posts: "Post 1" … "Post 23".
WITH RECURSIVE n(i) AS (SELECT 1 UNION ALL SELECT i + 1 FROM n WHERE i < 23)
INSERT INTO posts (title) SELECT 'Post ' || i FROM n;

paginate="true" makes the query return one page — the URL's ?page=, or the first — and fills posts_result.pagination with the totals. <ui:pager for="posts"> draws previous, the page numbers and next, keeping the URL's other parameters.

xml
<q:component name="Posts">
  <!-- paginate: the page is the URL's ?page= (page 1 without it). -->
  <q:query name="posts" datasource="db" paginate="true" page_size="10">
    SELECT id, title FROM posts ORDER BY id DESC
  </q:query>

  <ui:window title="Posts">
    <ui:text>
      {posts_result.pagination.startRecord}–{posts_result.pagination.endRecord}
      of {posts_result.pagination.totalRecords}
    </ui:text>
    <ui:list source="{posts}" as="p">
      <ui:item><ui:text>{p.title}</ui:text></ui:item>
    </ui:list>
    <!-- Previous, the page numbers, next — keeping the URL's other parameters. -->
    <ui:pager for="posts" />
  </ui:window>
</q:component>

A page that is not a positive number is page 1, never an error:

xml
<q:test name="the first page" page="/">
  <test:visit />
  <test:expect text="1–10 of 23" />
  <test:expect text="Post 23" />
  <test:expect text="Post 14" />
  <test:expect no-text="Post 13" />
</q:test>

<q:test name="the last page" page="/">
  <test:visit page="3" />
  <test:expect text="21–23 of 23" />
  <test:expect text="Post 1" />
  <test:expect no-text="Post 4" />
</q:test>

<q:test name="a page that is not a number is page 1" page="/">
  <test:visit page="abc" />
  <test:expect text="1–10 of 23" />
</q:test>
text
tests/posts.test.q
  PASS  the first page
  PASS  the last page
  PASS  a page that is not a number is page 1
3 passed, 0 failed

See DB-2, DB-9 and UI-11.

MIT Licensed · Built with VitePress