|
| 1 | +--- |
| 2 | +title: List Views (dc.List) |
| 3 | +sidebar_label: List Views |
| 4 | +sidebar_position: 100 |
| 5 | +--- |
| 6 | + |
| 7 | +List views, available as `dc.List`, generate pageable lists of results. They support grouping, heirarchies, paging, and several view modes. They come in three varieties: |
| 8 | + |
| 9 | +- **Unordered** (`unordered`): A bullet-point style list. |
| 10 | +- **Ordered** (`ordered`): A numbered list of items. |
| 11 | +- **Block**: (`block`): A list with no additional formatting - just shows elements in a vertical list of 'blocks'. |
| 12 | + |
| 13 | +## Quickstart |
| 14 | + |
| 15 | +Most common usages of lists will use `rows` and `renderer`: |
| 16 | + |
| 17 | +```jsx |
| 18 | +return function View() { |
| 19 | + // Start by fetching your data via a query. |
| 20 | + const data = dc.useQuery("#book and @page"); |
| 21 | + |
| 22 | + // Pass the full data to `rows`, and specify what to show in the list via `renderer`: |
| 23 | + return <dc.List rows={data} renderer={book => book.$link} />; |
| 24 | +} |
| 25 | +``` |
| 26 | + |
| 27 | +Lists are also commonly used for rendering embeds: |
| 28 | + |
| 29 | +```jsx |
| 30 | +return function View() { |
| 31 | + const data = dc.useQuery("#important-note and @block"); |
| 32 | + |
| 33 | + // Uses `dc.embed` to render an embed of all of the given blocks, with paging for performnace. |
| 34 | + return <dc.List rows={data} paging={true} renderer={dc.embed} />; |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +For the full set of available options, read on. |
| 39 | + |
| 40 | +## Basic Usage (`rows`) |
| 41 | + |
| 42 | +The list view is available in the local API as `dc.List`; it at a minimum requires a list of elements to show (`rows`): |
| 43 | + |
| 44 | +```js |
| 45 | +const ITEMS = ["First", "Second", "Third"]; |
| 46 | + |
| 47 | +return function View() { |
| 48 | + return <dc.List rows={ITEMS} />; |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +Which will produce a simple list like so: |
| 53 | + |
| 54 | +- First |
| 55 | +- Second |
| 56 | +- Third |
| 57 | + |
| 58 | +### List Types (`type`) |
| 59 | + |
| 60 | +You can control which of the list types you want via the `type` property. |
| 61 | + |
| 62 | +```js |
| 63 | +const ITEMS = ["First", "Second", "Third"]; |
| 64 | + |
| 65 | +return function View() { |
| 66 | + return <dc.List type="ordered" rows={ITEMS} />; |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +The three options available are: |
| 71 | + |
| 72 | +- **Unordered** (`unordered`): A bullet-point style list. This is the default. |
| 73 | +- **Ordered** (`ordered`): A numbered list of items. Numbering starts at 1 and increments. |
| 74 | +- **Block**: (`block`): A list with no additional formatting - just shows elements in a vertical list of 'blocks'. |
| 75 | + - Block formatting is best for embeds or other use cases where you do not want visible formatting from a regular list. |
| 76 | + |
| 77 | +### Specifying How To Render Data (`renderer`) |
| 78 | + |
| 79 | +When working with queries and any other non-trivial object, you will likely want to specify exactly what to render and how. This can be done via the `renderer` prop, which accepts a function that maps |
| 80 | +each row to the value or JSX to render. |
| 81 | + |
| 82 | +```jsx |
| 83 | +return function View() { |
| 84 | + // This will give back a set of MarkdownPage objects, which are not useful to render on their own. |
| 85 | + const books = dc.useQuery("#book and @page"); |
| 86 | + |
| 87 | + // Render books by rendering their links. |
| 88 | + return <dc.List rows={books} renderer={book => book.$link} />; |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +Some built-in rendering functions already exist, such as `dc.embed`, which renders embeds of files |
| 93 | +automatically: |
| 94 | + |
| 95 | +```jsx |
| 96 | +return function View() { |
| 97 | + // Fetch all blocks referencing a specific tag. |
| 98 | + const notes = dc.useQuery("#life-notes and @block"); |
| 99 | + |
| 100 | + // Render the notes as embeds in block format for minimal formatting. |
| 101 | + return <dc.List type="block" rows={notes} renderer={dc.embed} />; |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +### Paging (`paging` / `scrollOnPaging`) |
| 106 | + |
| 107 | +You can add paging to any list using the `paging` prop, which accepts several options. |
| 108 | + |
| 109 | +```js |
| 110 | +// Explicitly disable paging. |
| 111 | +<dc.List paging={false} ... /> |
| 112 | + |
| 113 | +// Enable paging, with the page size equal to your default page size in the Datacore settings. |
| 114 | +<dc.List paging={true} ... /> |
| 115 | + |
| 116 | +// Enable paging with the specific page size. |
| 117 | +<dc.List paging={10} ... /> |
| 118 | +``` |
| 119 | + |
| 120 | +If `paging` is not specified, it defaults to whatever your default paging configuration is in |
| 121 | +the Datacore settings. |
| 122 | + |
| 123 | +### Grouping (`groupings`) |
| 124 | + |
| 125 | +List views automatically support rendering grouped data; grouped data can be created most easily |
| 126 | +using [Data Array](data-array) syntax. |
| 127 | + |
| 128 | +```jsx |
| 129 | +return function View() { |
| 130 | + // Fetch all books and then group them by genre. |
| 131 | + const books = dc.useQuery("#book and @page"); |
| 132 | + const booksByGenre = dc.useArray(books, array => array.groupBy(book => book.value("genre"))); |
| 133 | + |
| 134 | + // No extra configuration is required by default to show groups. |
| 135 | + return <dc.List rows={booksByGenre} renderer={book => book.$link} />; |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +By default, grouped data will render the grouping headers using the default text renderer. If you'd |
| 140 | +like to add embellishments, such as converting each of the 'genres' in the above examples into links, |
| 141 | +you can use the `groupings` prop: |
| 142 | + |
| 143 | +```jsx |
| 144 | +return function View() { |
| 145 | + // Fetch all books and then group them by genre. |
| 146 | + const books = dc.useQuery("#book and @page"); |
| 147 | + const booksByGenre = dc.useArray(books, array => array.groupBy(book => book.value("genre"))); |
| 148 | + |
| 149 | + // Render each grouping key as a file link instead of just text. |
| 150 | + return <dc.List rows={booksByGenre} renderer={book => book.$link} groupings={(key) => dc.fileLink(key)} />; |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +You can also choose to construct an explicit `GroupingConfig` instead of passing a function: |
| 155 | + |
| 156 | +```jsx |
| 157 | +const LINK_GROUPING = { |
| 158 | + render: (key, rows) => dc.fileLink(key) |
| 159 | +}; |
| 160 | + |
| 161 | +return function View() { |
| 162 | + // Fetch all books and then group them by genre. |
| 163 | + const books = dc.useQuery("#book and @page"); |
| 164 | + const booksByGenre = dc.useArray(books, array => array.groupBy(book => book.value("genre"))); |
| 165 | + |
| 166 | + // Render each grouping key as a file link instead of just text. |
| 167 | + return <dc.List rows={booksByGenre} renderer={book => book.$link} groupings={LINK_GROUPING} />; |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +If you group multiple times, you can specify a separate rendering for each grouping level by passing an array of grouping configurations to `groupings`. |
| 172 | + |
| 173 | +### Heirarchies / Children (`childProp` / `maxChildDepth`) |
| 174 | + |
| 175 | +## Full Reference |
| 176 | + |
| 177 | +The full set of available properties is provided below: |
| 178 | + |
| 179 | +```js |
| 180 | +export interface ListState<T> { |
| 181 | + /** |
| 182 | + * Whether the list should be ordered, unordered, or block. |
| 183 | + * |
| 184 | + * Block lists do not use an actual list element and instead just render a series of contiguous |
| 185 | + * div elements with no other annotations. |
| 186 | + */ |
| 187 | + type?: "ordered" | "unordered" | "block"; |
| 188 | + |
| 189 | + /** The full collection of elements in the list. */ |
| 190 | + rows: Grouping<T>; |
| 191 | + |
| 192 | + /** Allows for grouping header lines to be overridden with custom rendering/logic. */ |
| 193 | + groupings?: GroupingConfig<T> | GroupingConfig<T>[] | ((key: Literal, rows: Grouping<T>) => Literal | VNode); |
| 194 | + |
| 195 | + /** |
| 196 | + * Custom render function to use for rendering each leaf element. Can produce either JSX or a plain value which will be |
| 197 | + * rendered as a literal. |
| 198 | + */ |
| 199 | + renderer?: (row: T) => React.ReactNode | Literal; |
| 200 | + |
| 201 | + /** Controls whether paging is enabled for this element. If true, uses default page size. If a number, paging is enabled with the given page size. */ |
| 202 | + paging?: boolean | number; |
| 203 | + |
| 204 | + /** |
| 205 | + * Whether the view will scroll to the top automatically on page changes. If true, will always scroll on page changes. |
| 206 | + * If a number, will scroll only if the number is greater than the current page size. |
| 207 | + **/ |
| 208 | + scrollOnPaging?: boolean | number; |
| 209 | + |
| 210 | + /** Maximum level of children that will be rendered; a level of 0 means no children expansion will occur. */ |
| 211 | + maxChildDepth?: number; |
| 212 | + |
| 213 | + /** |
| 214 | + * Property name, list of property names, or function to be applied to obtain children for a given entry. |
| 215 | + * Defaults to the `$children` and `children` props. |
| 216 | + * |
| 217 | + * If null, child extraction is disabled and no children will be fetched. If undefined, uses the default. |
| 218 | + */ |
| 219 | + childProp?: null | string | string[] | ((row: T) => T[]); |
| 220 | +} |
| 221 | + |
| 222 | +export interface GroupingConfig<T> { |
| 223 | + /** How a grouping with the given key and set of rows should be rendered. */ |
| 224 | + render?: (key: Literal, rows: Grouping<T>) => Literal | VNode; |
| 225 | +} |
| 226 | +``` |
0 commit comments