Custom Array Row Label
payload-extra-fields/array-row-labelFreeItem
A custom array row label component for PayloadCMS.
Install it
npx shadcn@latest add https://payload.veiag.dev/r/array-row-label.jsonSource
1'use client'2import { useRowLabel } from '@payloadcms/ui'3import { ArrayRowLabelArgs } from './types'4import { useMemo } from 'react'56/**7 * Helper function to get nested value from an object using dot notation8 * e.g. getNestedValue(obj, 'nested.fieldName')9 */10const getNestedValue = (obj: unknown, path: string): unknown => {11 return path.split('.').reduce((acc, part) => {12 if (acc && typeof acc === 'object' && acc !== null && part in acc) {13 return (acc as Record<string, unknown>)[part]14 }15 return undefined16 }, obj)17}1819/**20 * Helper function to check if all field variables in a template are empty21 */22const hasEmptyFieldValues = (template: string, data: unknown): boolean => {23 const fieldMatches = template.match(/{{\s*([\w.]+)\s*}}/g)2425 if (!fieldMatches) {26 return false27 }2829 // Check if all field variables (excluding 'index') are empty30 return fieldMatches.every((match) => {31 const fieldPath = match.replace(/{{\s*|\s*}}/g, '')3233 // Skip 'index' as it's always populated34 if (fieldPath === 'index') {35 return false36 }3738 const value = getNestedValue(data, fieldPath)39 return !value || (typeof value === 'string' && value.trim() === '')40 })41}4243/**44 * Helper function to process template strings with variable replacement45 */46const processTemplate = (template: string, data: unknown, rowNumber?: number): string => {47 let result = template.replace(/{{\s*index\s*}}/g, String(rowNumber || 0))4849 result = result.replace(/{{\s*([\w.]+)\s*}}/g, (_, fieldPath) => {50 const value = getNestedValue(data, fieldPath)51 if (typeof value === 'string' || typeof value === 'number') {52 return String(value)53 }54 return ''55 })5657 return result58}5960const ArrayCustomLabel: React.FC<ArrayRowLabelArgs> = ({61 fieldToUse,62 template = false,63 fallbackLabel = 'Item {{index}}',64}) => {65 // eslint-disable-next-line @typescript-eslint/no-explicit-any66 const { data, rowNumber } = useRowLabel<any>()6768 const customLabel = useMemo(() => {69 let labelValue = ''70 let shouldUseFallback = false7172 if (!template) {73 // Simple field mode74 const value = getNestedValue(data, fieldToUse)75 if (typeof value === 'string' || typeof value === 'number') {76 labelValue = String(value).trim()77 }78 shouldUseFallback = !labelValue79 } else {80 // Template mode - check if all field values are empty81 shouldUseFallback = hasEmptyFieldValues(fieldToUse, data)8283 if (!shouldUseFallback) {84// … truncated
Files it writes
More from payload-extra-fields
All 4 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Color Pickercolor-picker | payload-extra-fields | Other | Free | no deps · 4 files | |
| Lucide Icon Pickerlucide-icon-picker | payload-extra-fields | Other | Free | 4 deps · 5 files | |
| Slug Fieldslug | payload-extra-fields | Other | Free | no deps · 6 files |
