obsidian/wiki/payloadcms/query-presets.md
2026-05-15 16:35:48 +01:00

5.1 KiB

title aliases tags sources created updated
Query Presets
query-presets
payload-query-presets
saved-filters
payloadcms
admin
collections
access-control
list-view
raw/query-presets__overview.md
2026-05-15 2026-05-15

Overview

Query Presets allow users to save and share filters, columns, and sort orders for Collections. Each preset is stored as a record in the payload-query-presets built-in collection — so presets are user-defined at runtime, not hard-coded in config.

Presets are applied in the Admin Panel List View. When enabled, extra controls appear for managing presets.

Enabling on a Collection

import type { CollectionConfig } from 'payload'

export const MyCollection: CollectionConfig = {
  slug: 'my-collection',
  enableQueryPresets: true,  // <-- this is all that's required
}

Config Options

All settings live under queryPresets at the root of buildConfig:

const config = buildConfig({
  queryPresets: {
    access: { ... },          // collection-level access control
    filterConstraints: ...,   // dynamically filter which constraints are available
    constraints: { ... },     // document-level custom access rules
    labels: { ... },          // custom UI labels
  },
})
Option Description
access Collection-level access — applies to all presets, statically defined
filterConstraints Dynamically hide/disable constraint options per user
constraints Document-level custom access control options (RBAC etc.)
labels Custom labels for the presets collection in the admin UI

Access Control

Two layers of access control exist:

1. Collection Access Control

Applies to all presets. Not user-controllable — defined statically in config.

queryPresets: {
  access: {
    read: ({ req: { user } }) =>
      user?.roles?.some((role) => role === 'admin') ?? false,
    update: ({ req: { user } }) =>
      user?.roles?.some((role) => role === 'admin') ?? false,
  },
}

Warning: Custom access overrides defaults — including the authentication requirement. Always add an explicit auth check unless public access is intended.

2. Document Access Control

Applies per-preset. Users can configure these in the Admin Panel UI. Built-in options:

  • Only Me — only the creator can read/update/delete
  • Everyone — all authenticated users
  • Specific Users — select individual users

Custom Constraints (RBAC example)

queryPresets: {
  constraints: {
    read: [
      {
        label: 'Specific Roles',
        value: 'specificRoles',
        fields: [
          {
            name: 'roles',
            type: 'select',
            hasMany: true,
            options: [
              { label: 'Admin', value: 'admin' },
              { label: 'User', value: 'user' },
            ],
          },
        ],
        // Payload wraps custom fields inside `access[operation]` group
        access: ({ req: { user } }) => ({
          'access.read.roles': { in: [user?.roles] },
        }),
      },
    ],
  },
}

Each constraint entry requires:

Option Description
label Display name in the dropdown
value DB-stored identifier
fields Fields rendered when this option is selected
access Function returning the Where query that enforces the rule

Gotcha: Custom fields are stored under access[operation], so filter paths must be prefixed accordingly (e.g. access.read.roles).

Filter Constraints

Dynamically control which constraint options are available based on the current user:

queryPresets: {
  filterConstraints: ({ req, options }) =>
    !req.user?.roles?.includes('admin')
      ? options.filter(
          (option) =>
            (typeof option === 'string' ? option : option.value) !== 'everyone',
        )
      : options,
}

This example prevents non-admin users from setting a preset to "everyone". Hidden options are disabled (not removed) if a preset already uses them.

Key Takeaways

  • Enable with a single enableQueryPresets: true on any Collection — no schema changes needed
  • Presets are stored as records in the auto-created payload-query-presets collection
  • Two access layers: collection-level (static, admin-set) and document-level (user-set per preset)
  • Custom constraints enable RBAC — use access[operation].fieldName path prefix for Where queries
  • filterConstraints lets you hide constraint options from users without the right permissions
  • Overriding queryPresets.access removes the default auth requirement — always add explicit user checks

Sources