Files
nocodb/packages/nc-gui/components/nc/form-builder/input/SelectField.vue
mertmit 69a29568c7 chore: sync
Signed-off-by: mertmit <mertmit99@gmail.com>
2026-01-10 00:21:02 +03:00

115 lines
3.7 KiB
Vue

<script lang="ts" setup>
import type { ColumnType } from 'nocodb-sdk'
interface Props {
value?: string | string[] | null
tableId?: string
options?: any[]
multiple?: boolean
disabled?: boolean
}
const props = defineProps<Props>()
const emit = defineEmits<{
'update:value': [value: string | string[] | null | undefined]
}>()
const modelValue = useVModel(props, 'value', emit)
const isOpenColumnSelectDropdown = ref(false)
const columnList = computed(() => {
return (props.options || []).map((opt: any) => ({
label: opt.label,
value: opt.value,
ncItemDisabled: opt.ncItemDisabled || false,
ncItemTooltip: opt.ncItemTooltip || '',
...opt,
}))
})
const columnListMap = computed(() => {
if (!columnList.value || columnList.value.length === 0) return new Map()
return new Map(columnList.value.map((column) => [column.value, column]))
})
const selectedColumn = computed(() => {
if (!columnListMap.value || columnListMap.value.size === 0) return undefined
if (props.multiple && Array.isArray(modelValue.value)) {
return modelValue.value.map((val) => columnListMap.value.get(val)).filter(Boolean)
}
return columnListMap.value.get(modelValue.value as string) || undefined
})
const selectedColumnLabel = computed(() => {
if (!selectedColumn.value) return '-- Select field --'
if (Array.isArray(selectedColumn.value)) {
return selectedColumn.value.length > 0
? `${selectedColumn.value.length} field${selectedColumn.value.length > 1 ? 's' : ''} selected`
: '-- Select field --'
}
return selectedColumn.value.label
})
const handleValueUpdate = (value: any) => {
modelValue.value = value
}
</script>
<template>
<NcListDropdown v-model:is-open="isOpenColumnSelectDropdown" :disabled="disabled" :has-error="!!selectedColumn?.ncItemDisabled">
<div class="flex-1 flex items-center gap-2 min-w-0">
<div v-if="selectedColumn && !Array.isArray(selectedColumn)" class="min-w-5 flex items-center justify-center">
<SmartsheetHeaderIcon :column="selectedColumn.column as ColumnType" color="text-nc-content-gray-muted" />
</div>
<NcTooltip hide-on-click class="flex-1 truncate" show-on-truncate-only>
<span
class="text-sm flex-1 truncate"
:class="{
'text-nc-content-gray-muted': !selectedColumn || (Array.isArray(selectedColumn) && selectedColumn.length === 0),
}"
>
{{ selectedColumnLabel }}
</span>
<template #title>
{{ selectedColumnLabel }}
</template>
</NcTooltip>
<GeneralIcon
v-if="selectedColumn && !disabled"
class="hidden text-nc-content-gray-muted transition group-hover:!block h-4 w-4 cursor-pointer"
icon="ncXCircle"
@click.stop="handleValueUpdate(null)"
/>
<GeneralIcon
icon="ncChevronDown"
class="flex-none h-4 w-4 transition-transform opacity-70"
:class="{ 'transform rotate-180': isOpenColumnSelectDropdown }"
/>
</div>
<template #overlay="{ onEsc }">
<NcList
v-model:open="isOpenColumnSelectDropdown"
:value="multiple ? (Array.isArray(modelValue) ? modelValue : []) : modelValue || ''"
:list="columnList"
variant="medium"
:close-on-select="!multiple"
:is-multi-select="multiple"
class="!w-auto"
wrapper-class-name="!h-auto"
@update:value="handleValueUpdate"
@escape="onEsc"
>
<template #listItemExtraLeft="{ option }">
<div class="min-w-5 flex items-center justify-center">
<SmartsheetHeaderIcon :column="option.column as ColumnType" color="text-nc-content-gray-muted" />
</div>
</template>
</NcList>
</template>
</NcListDropdown>
</template>