3. List and detail
Our screen lists authors and acts on them, but the actions hang off a lone button, and there’s nowhere to see an author — their books, in particular. The everyday shape for this is a table on the left, details on the right, with a toolbar that knows whether a row is selected. That layout has enough moving pieces to deserve a component; DataPage hands it to you whole.
We’ll point it at AllAuthorsWithBooks — the read model from the Arc tutorial where each author already carries their books — so the detail panel has something to show.
-
Describe the detail panel. It’s an ordinary component that receives the selected
item. Because eachAuthorWithBookscarries itsbooks, listing them is amap— no second query:AuthorDetails.tsx export const AuthorDetails = ({ item }) => (<div className="p-4"><h2>{item.name}</h2><h3>Books</h3><ul>{item.books.map(book => <li key={String(book.id)}>{book.title}</li>)}</ul></div>); -
Assemble the page.
DataPagetakes the query, the columns, the menu actions, and the detail component. Selection, the resizable split, and hiding the panel when nothing is selected all come built in:Authors.tsx import { DataPage, MenuItem } from '@cratis/components/DataPage';import { Column } from 'primereact/column';import { useDialog } from '@cratis/arc.react/dialogs';import { AllAuthorsWithBooks } from './Authors/AuthorWithBooks'; // generated proxyimport { AddAuthor } from './AddAuthor';import { AuthorDetails } from './AuthorDetails';export const Authors = () => {const [AddAuthorDialog, showAddAuthor] = useDialog(AddAuthor);return (<><DataPagetitle="Authors"query={AllAuthorsWithBooks}emptyMessage="No authors yet"detailsComponent={AuthorDetails}><DataPage.MenuItems><MenuItem label="Add author" icon="pi pi-plus" command={() => showAddAuthor()} /><MenuItem label="Edit" icon="pi pi-pencil" disableOnUnselected command={() => {/* open RenameAuthor */}} /></DataPage.MenuItems><DataPage.Columns><Column field="name" header="Name" sortable /></DataPage.Columns></DataPage><AddAuthorDialog /></>);};
Select an author and their books appear on the right. Drag the divider to resize. The Edit item is disabled until a row is selected — disableOnUnselected wires that to selection for you.
Look back at what you built
Section titled “Look back at what you built”Three chapters ago we had a generated query and no screen. Now we have a real library back office:
- Chapter 1 — a live table from
AllAuthors, bound to an observable query with no fetch or subscription code. - Chapter 2 — add, rename, and remove through
CommandDialog+useDialog, with the table updating itself the instant a command lands. - Chapter 3 — a
DataPagelist-and-detail layout: selection, menu actions, and a resizable panel showing each author’s books.
The pattern under all of it is the same one Components exists to give you: point a component at a generated proxy, and the wiring is already done. A query becomes a live table; a command becomes a validated form; a read model becomes a detail panel — and every one of them stays type-checked against the C# it came from.
Where to go next
Section titled “Where to go next”- Building a form and Displaying data — the two halves in full, including every field type and table option.
- A list screen with actions — the same screen as a quick recipe to copy.
- Choosing a component — a decision guide from “what’s on the screen” to the right component.
- Build a full-stack feature — the backend and this front end, assembled end to end.
You’ve built a screen, and you have the pattern for every other one. That’s Components doing its job — go build the rest of your app.