selectMultipleField
Pick several options from a static list, a table, or another section. Stored as a list or as rows in a join table.
import { selectMultipleField } from 'nextjs-cms/core/fields'Basic usage
selectMultipleField({
name: 'features',
options: [
{ value: 'wifi', label: 'Wi-Fi' },
{ value: 'parking', label: 'Parking' },
{ value: 'pool', label: 'Pool' },
],
})Selected values are stored comma-separated in one column: wifi,pool.
With every option
selectMultipleField({
name: 'collections',
label: { en: 'Collections', ar: 'المجموعات' },
required: true,
order: 6,
localized: false,
conditionalRules: [{ field: isListed, condition: 'equals', value: true }],
// one source:
section: collectionsSection,
// options: [...],
// db: { table, identifier, label, orderBy, identifierType, labelType },
checkValuesExist: true,
destinationDb: {
table: 'product_collections',
itemIdentifier: 'product_id',
selectIdentifier: 'collection_id',
},
})Options
| Option | Type | Default | Description |
|---|---|---|---|
options | { value, label }[] | none | Static options. |
section | a has-items or category section | none | Another section's items as options. |
db | { table, identifier, label, orderBy?, identifierType?, labelType? } | none | Options from a table. Same as selectField db. |
checkValuesExist | boolean | true | Verify every submitted value is a real option. On by default, unlike selectField. |
destinationDb | { table, itemIdentifier, selectIdentifier } | none | One row per selected value in a join table. Recommended for relationships. |
Plus the common options. Exactly one of options, section, or db.
Two storage modes
Without destinationDb: a comma-separated column
selectMultipleField({ name: 'features', options: [/* ... */] })properties
id │ title │ features
───┼────────────────┼──────────────────
1 │ Seaside villa │ wifi,pool,parking
2 │ City studio │ wifiSimple, and fine for short static lists you only display. But the column is VARCHAR(255), so long selections can overflow it, and "all properties with a pool" needs FIND_IN_SET('pool', features), which can't use an index.
With destinationDb: a join table
selectMultipleField({
name: 'features',
options: [/* ... */],
destinationDb: { table: 'property_features', itemIdentifier: 'property_id', selectIdentifier: 'feature' },
})property_features
property_id │ feature
────────────┼─────────
1 │ wifi
1 │ pool
1 │ parking
2 │ wifiupdate-sectionscreates the table. Its primary key is(itemIdentifier, selectIdentifier), anditemIdentifierhas the same type as the section's identifier.- The section's own table gets no
featurescolumn. - On every save, the item's rows are replaced with the current selection. Deleting the item deletes its rows.
- If the field is
localized, the join table gets alocalecolumn and each language has its own selection.
This is the right choice for real relationships: tags, categories, related products.
destinationDb sub-options
| Sub-option | Description |
|---|---|
table | Join table name. Must not end in _locales. |
itemIdentifier | Column holding this item's identifier (post_id). |
selectIdentifier | Column holding the selected option's value (tag_id). |
Examples
Blog posts in several topics
import topicsSection from './topics.section'
selectMultipleField({
name: 'topics',
section: topicsSection,
required: true,
destinationDb: { table: 'post_topics', itemIdentifier: 'post_id', selectIdentifier: 'topic_id' },
})Query on your website:
import { eq } from 'drizzle-orm'
// All posts in topic 7
const rows = await db
.select({ post: PostsTable })
.from(PostTopicsTable)
.innerJoin(PostsTable, eq(PostsTable.id, PostTopicsTable.postId))
.where(eq(PostTopicsTable.topicId, 7))Languages spoken (static, comma-separated)
selectMultipleField({
name: 'languages',
options: [
{ value: 'en', label: 'English' },
{ value: 'ar', label: 'Arabic' },
{ value: 'tr', label: 'Turkish' },
],
})
// Website: row.languages?.split(',') ?? []Storage
| Mode | Column | Value |
|---|---|---|
| Default | VARCHAR(255) | Comma-separated values: a,b,c |
destinationDb | none | One row per value in the join table |