multi selectable card setting (#38)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<!-- ONLY FOR TEST FOR NOW-->
|
||||
<form class="flex flex-col space-y-4 form-json-form">
|
||||
<span>Settings</span>
|
||||
<FormJsonForm :schema="jsonSchema" @change="onParamsFormChange"></FormJsonForm>
|
||||
</form>
|
||||
</template>
|
||||
@@ -21,6 +20,11 @@ const jsonSchema = {
|
||||
type: 'string',
|
||||
title: 'Favorite Color',
|
||||
enum: ['red', 'green', 'blue']
|
||||
},
|
||||
multiSelect: {
|
||||
type: 'array',
|
||||
title: 'Multi Favorite Chars',
|
||||
enum: ['a', 'b', 'c', 'd']
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +32,6 @@ const jsonSchema = {
|
||||
const paramsFormState = ref<JsonFormsChangeEvent>()
|
||||
const onParamsFormChange = (e: JsonFormsChangeEvent) => {
|
||||
paramsFormState.value = e
|
||||
console.log(JSON.stringify(e))
|
||||
console.log(e)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-foreground-2 text-body-2xs mb-1 pl-1">
|
||||
{{ control.label }}
|
||||
</div>
|
||||
<FormSelectMulti
|
||||
:model-value="modelValue"
|
||||
:name="fieldName"
|
||||
:rules="multiValidator"
|
||||
:label="control.label"
|
||||
:items="control.options"
|
||||
clearable
|
||||
:search="true"
|
||||
:search-placeholder="'Search'"
|
||||
:filter-predicate="searchFilterPredicate"
|
||||
:help="control.description"
|
||||
:allow-unset="false"
|
||||
by="value"
|
||||
button-style="tinted"
|
||||
:validate-on-value-update="validateOnValueUpdate"
|
||||
mount-menu-on-body
|
||||
@update:model-value="handleChange"
|
||||
>
|
||||
<template #nothing-selected>
|
||||
{{
|
||||
appliedOptions['placeholder']
|
||||
? appliedOptions['placeholder']
|
||||
: 'Select values'
|
||||
}}
|
||||
</template>
|
||||
<template #something-selected="{ value }">
|
||||
<div ref="elementToWatchForChanges" class="flex items-center space-x-0.5">
|
||||
<div ref="itemContainer" class="flex flex-wrap overflow-hidden space-x-0.5">
|
||||
<div v-for="(item, i) in value" :key="item.value" class="text-foreground">
|
||||
{{ item.label + (i < value.length - 1 ? ', ' : '') }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="hiddenSelectedItemCount > 0" class="text-foreground-2 normal">
|
||||
+{{ hiddenSelectedItemCount }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #option="{ item }">
|
||||
<div class="flex items-center text-foreground-2 text-body-2xs">
|
||||
<span class="truncate">{{ item.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</FormSelectMulti>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { ControlElement } from '@jsonforms/core'
|
||||
import { rendererProps, useJsonFormsEnumControl } from '@jsonforms/vue'
|
||||
import type { Nullable } from '@speckle/shared'
|
||||
import { useFormSelectChildInternals } from '@speckle/ui-components'
|
||||
import type { GenericValidateFunction } from 'vee-validate'
|
||||
import { useJsonRendererBaseSetup } from '~/lib/form/composables/jsonRenderers'
|
||||
|
||||
type OptionType = { value: string; label: string }
|
||||
type ValueType = OptionType | OptionType[] | undefined
|
||||
|
||||
const emit = defineEmits<(e: 'update:modelValue', v: ValueType) => void>()
|
||||
|
||||
const props = defineProps({
|
||||
...rendererProps<ControlElement>(),
|
||||
// TODO: Doesn't appear that jsonforms properly supports multiple selection
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
controlOverrides: {
|
||||
type: Object as PropType<Nullable<ReturnType<typeof useJsonFormsEnumControl>>>,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const searchFilterPredicate = (item: OptionType, search: string) =>
|
||||
item.label.toLocaleLowerCase().includes(search.toLocaleLowerCase())
|
||||
|
||||
const elementToWatchForChanges = ref(null as Nullable<HTMLElement>)
|
||||
const itemContainer = ref(null as Nullable<HTMLElement>)
|
||||
|
||||
const { hiddenSelectedItemCount, isArrayValue } =
|
||||
useFormSelectChildInternals<OptionType>({
|
||||
props: toRefs(props),
|
||||
emit,
|
||||
dynamicVisibility: { elementToWatchForChanges, itemContainer }
|
||||
})
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const multiValidator: GenericValidateFunction<any> = () => true // ignoring validation for multi enum since it is custom and jsonforms does not support it properly
|
||||
|
||||
const { handleChange, control, appliedOptions, fieldName, validateOnValueUpdate } =
|
||||
useJsonRendererBaseSetup(props.controlOverrides || useJsonFormsEnumControl(props), {
|
||||
onChangeValueConverter: (newVal: ValueType) => {
|
||||
if (props.multiple && isArrayValue(newVal)) {
|
||||
return newVal.map((v) => v.value)
|
||||
} else if (newVal && !props.multiple && !isArrayValue(newVal)) {
|
||||
return newVal.value
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const modelValue = computed(() => {
|
||||
const val = control.value.data as OptionType[]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
return control.value.options.filter((o) => val?.includes(o.value))
|
||||
})
|
||||
</script>
|
||||
@@ -7,8 +7,8 @@
|
||||
:label="control.label"
|
||||
:placeholder="appliedOptions['placeholder']"
|
||||
:help="control.description"
|
||||
color="foundation"
|
||||
show-label
|
||||
size="lg"
|
||||
:validate-on-value-update="validateOnValueUpdate"
|
||||
@update:model-value="handleChange"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user