Skip to content

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 ​

ParameterDefaultDescription
modelPbResourceModel short name, resolved under PageBlocks\App\Models\. An unknown name is logged and renders nothing.
tplpageblocks.resourceChunk 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.
parentShorthand for "owned by resource N" (model_id = N).
parent_typemodDocumentMorph class of the owner, when it is not a resource.
whereConditions as JSON: {"template":4} or [["price",">=","100"]].
scopespublishedEloquent scopes, comma-separated. Pass an empty value to disable.
orderBy / sortbymenuindex"menuindex", "menuindex desc" or JSON {"price":"desc"}.
limit10Rows per page.
offset0Skip 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.
sortdirascDirection for the columns of sortby that do not spell one out. An explicit sortby='price desc' wins.
tplWrapperChunk 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.
tplEmptyChunk rendered instead of the rows when nothing was found. Pagination and the "load more" button are then not rendered at all.
outputSeparator\nGlue between rendered rows; applies to the AJAX pages too.
toPlaceholderPut the output into a MODX placeholder and return nothing.
classd-flex flex-column gap-3CSS classes of the wrapper.
loadmoreRender a "load more" button instead of relying on page links.
loadmoreLabelПоказать ещёButton caption.
showLogPrint the reason for an empty list next to the output; manager-only. See Intro.

What it renders ​

html
<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:

php
{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.

© PageBlocks 2019-present