pbList
Universal lister with built-in pagination. Point it at a model, give it a chunk, get a paginated list — without writing a controller for it.
[[!pbList]]
[[!pbList? &model=`PbResource` &parent=`[[*id]]` &tpl=`myItem` &limit=`10`]]The bare call is deliberate: without a single parameter it lists published PbResource rows through the default chunk pageblocks.resource, which the package installs as an ordinary chunk you can find in the element tree and edit.
Parameters
| Parameter | Default | Description |
|---|---|---|
model | PbResource | Model short name, resolved under PageBlocks\App\Models\. An unknown name is logged and renders nothing. |
tpl | pageblocks.resource | Chunk for one row, receives item. Same spelling as everywhere else in PageBlocks: a bare name is a chunk from the database, file:chunks/card is a file, @INLINE <b>{$item->pagetitle}</b> is a template inline. |
parent | Shorthand for "owned by resource N" (model_id = N). | |
parent_type | modDocument | Morph class of the owner, when it is not a resource. |
where | Conditions as JSON: {"template":4} or [["price",">=","100"]]. | |
scopes | published | Eloquent scopes, comma-separated. Pass an empty value to disable. |
orderBy / sortby | menuindex | "menuindex", "menuindex desc" or JSON {"price":"desc"}. |
limit | 10 | Rows per page. |
offset | 0 | Skip this many rows before the first page. total shrinks by the same amount, so the last page does not promise rows that are no longer there. |
sortdir | asc | Direction for the columns of sortby that do not spell one out. An explicit sortby='price desc' wins. |
tplWrapper | Chunk wrapping the whole output — the #pb-items container and the pagination — and receiving output and total. It stays outside on purpose: AJAX replaces the contents of #pb-items and "load more" appends to it, so a wrapper inside would be duplicated on every fetch. | |
tplEmpty | Chunk rendered instead of the rows when nothing was found. Pagination and the "load more" button are then not rendered at all. | |
outputSeparator | \n | Glue between rendered rows; applies to the AJAX pages too. |
toPlaceholder | Put the output into a MODX placeholder and return nothing. | |
class | d-flex flex-column gap-3 | CSS classes of the wrapper. |
loadmore | Render a "load more" button instead of relying on page links. | |
loadmoreLabel | Показать ещё | Button caption. |
showLog | Print the reason for an empty list next to the output; manager-only. See Intro. |
What it renders
<div class="d-flex flex-column gap-3" id="pb-items"
data-pb-key="pblist2_a1b2…" data-pb-total="137" data-pb-last-page="14">
<!-- rows rendered through tpl -->
</div>
<div class="pb-pagination mt-4" pb-pagination>
<!-- numbered links -->
</div>data-pb-key is a hash of the resolved query, cached server-side. Pagination sends that one key back over AJAX, so the browser never sees — and cannot tamper with — the conditions. Without JavaScript the numbered links still work: they carry ?page=N and re-run the snippet server-side.
Examples
Children of the current resource
[[!pbList? &parent=`[[*id]]` &tpl=`childItem` &limit=`20`]]Another model, filtered and sorted
[[!pbList?
&model=`PbVacancy`
&tpl=`vacancyCard`
&where=`{"city_id":7}`
&orderBy=`{"published_at":"desc"}`
&limit=`12`
]]"Load more" instead of page numbers
[[!pbList? &parent=`[[*id]]` &tpl=`childItem` &loadmore=`1` &limit=`9`]]From a Fenom template
Named parameters, Smarty style — space separated, no parentheses and no commas:
{pbList model='PbResource' parent=$modx->resource->id tpl='childItem' limit=10}tpl means the same here as in the tag above — a bare name is the chunk childItem from the database. For a file, spell the source out: tpl='file:chunks/childItem'.
chunk: is deprecated
Up to alfa16 pbList read a bare name as a file under core/App/elements/chunks/, and chunk: was how you reached the database — the opposite of every other snippet, so &tpl=`card` meant two different things in pbList and pbResources. A bare name is now the database everywhere. chunk: still works for one major version and writes a deprecation line into the MODX log; drop the prefix and the call means the same thing.
A chunk that does not exist renders as nothing
A missing template does not break the page: the output is empty and the reason goes to the MODX error log. To see it on the page itself add &showLog=`1` — the block is shown to a user logged into the manager. An empty list with a non-zero data-pb-total usually means a typo in tpl.