Skip to main content
Glama
VormInputOption.vue4.95 kB
/* This component is tightly coupled with the VormInput component and is only meant to be used within it specifically it's only for VormInputs with type = dropdown | radio | multi-checkbox */ <template> <option v-if=" parentInputType === 'dropdown' || parentInputType === 'dropdown-optgroup' " class="vorm-input-option" :value="safeOptionValue" :selected="dropdownOptionSelected" :disabled="disabledBySelfOrParent" > <slot>{{ value }}</slot> </option> <label v-else-if="parentInputType === 'radio'" class="vorm-input-option"> <input class="vorm-input-option__input" type="radio" :value="safeOptionValue" :name="radioName" :disabled="disabledBySelfOrParent" :checked="value === parentValue" @focus="onFocus" @blur="onBlur" @change="onChange" /> <div> <slot>{{ value }}</slot> </div> </label> <label v-else-if="parentInputType === 'multi-checkbox'" class="vorm-input-option" > <input class="vorm-input-option__input" type="checkbox" :value="safeOptionValue" :disabled="disabledBySelfOrParent" :checked="parentValue?.indexOf(value) > -1" @focus="onFocus" @blur="onBlur" @change="onMultiCheckboxChange" /> <div> <slot>{{ value }}</slot> </div> </label> </template> <script lang="ts" setup> import { computed, onMounted, toRefs, getCurrentInstance, onBeforeUnmount, toRaw, toRef, unref, } from "vue"; import * as _ from "lodash-es"; import { useDisabledBySelfOrParent } from "./helpers/form-disabling"; import type { PropType } from "vue"; const props = defineProps({ value: [String, Number, Boolean] as PropType< string | number | boolean | null >, disabled: Boolean, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const vormInputParent = getCurrentInstance()?.parent as any; // NOTE - having some issues with vue deciding when to reuse inputs from within Stack // which was causing this exposed data to be incorrect... instead using the props directly seems to fix it // const parentInputType = vormInputParent?.exposed?.vormInputType; // this causes some issues in very specific cases const parentInputType = vormInputParent.props.type; // this seems to work fine const parentValue = computed(() => unref(vormInputParent?.exposed?.currentValue), ); // this is tightly coupled component only meant to be used within a VormInput const VALID_PARENT_INPUT_TYPES = [ "dropdown", "radio", "multi-checkbox", "dropdown-optgroup", ]; if (!VALID_PARENT_INPUT_TYPES.includes(parentInputType)) { throw new Error( "VormInputOption can only be used inside VormInput with type = dropdown/radio/multi-checkbox", ); } const { disabled } = toRefs(props); const disabledBySelfOrParent = useDisabledBySelfOrParent(disabled); // set value used for select (dropdown) options - which have some extra handling for empty/null // because otherwise it will default to the text content const safeOptionValue = computed(() => { if (parentInputType === "dropdown") { if (props.value === undefined) return "_null_"; if (props.value === null) return "_null_"; return props.value?.toString(); } return props.value; }); const dropdownOptionSelected = computed( () => parentInputType === "dropdown" && props.value === parentValue.value, ); const radioName = vormInputParent?.exposed.formInputId; function onBlur() { vormInputParent?.exposed.onChildInputOptionBlur(); } function onFocus() { vormInputParent?.exposed.onChildInputOptionFocus(); } function onChange() { // use props.value instead of the native js event target value // to avoid any other transformation (converting to string) vormInputParent?.exposed.onChildInputOptionChange(props.value); } function onMultiCheckboxChange() { const currentValue = toRaw(parentValue.value); let newValue; // emit new array rather than modifying so reactive change is noticed if (_.includes(currentValue, props.value)) { newValue = _.without(currentValue || [], props.value); } else { newValue = [...(currentValue || []), props.value]; } vormInputParent?.exposed.onChildInputOptionChange( newValue.length ? newValue : null, ); } // register each option with parent input component const thisComponent = getCurrentInstance(); onMounted(() => { vormInputParent?.exposed.registerChildInputOption(thisComponent); }); onBeforeUnmount(() => { vormInputParent?.exposed.unregisterChildInputOption(thisComponent); }); // expose the value so the parent can access it defineExpose({ optionValue: toRef(props, "value"), // have to expose a ref or value gets stuck if the component is reused }); </script> <style lang="less"> label.vorm-input-option { display: flex; flex-direction: row; align-items: center; padding-bottom: 0.25rem; } .vorm-input-option__input { margin-right: 8px; } </style>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server