PluginProbe
The Innovative Form Builder – IvyForms / 0.4
The Innovative Form Builder – IvyForms v0.4
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / views / public / fields / RadioFormField.vue

RadioFormField.vue in The Innovative Form Builder – IvyForms 0.4, at frontend/src/views/public/fields/RadioFormField.vue

107 lines 2.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div
3 :class="[
4 'ivyforms-field',
5 'ivyforms-field__radio',
6 'ivyforms-field__radio_' + field.id,
7 field.cssClasses,
8 ]"
9 >
10 <IvyFormItem
11 :label="field.hideLabel ? '' : field.label"
12 :required="field.required"
13 :error="error"
14 :prop="field.type + '_' + field.fieldIndex"
15 :show-info="!!field.description && !error"
16 :info-text="String(field.description || '')"
17 >
18 <IvyRadioGroup
19 :id="fieldID"
20 v-model="localModelValue"
21 :disabled="disabled"
22 :readonly="field.readOnly"
23 :required="field.required"
24 :direction="'horizontal'"
25 class="ivyforms-field__radio-group ivyforms-flex ivyforms-gap-8"
26 >
27 <IvyRadio
28 v-for="option in radioOptions"
29 :id="option.id"
30 :key="option.id || option.value"
31 :value="option.value"
32 priority="secondary"
33 class="ivyforms-field__radio-option"
34 >
35 {{ option.label }}
36 </IvyRadio>
37 </IvyRadioGroup>
38 </IvyFormItem>
39 </div>
40 </template>
41
42 <script setup lang="ts">
43 import { computed, ref, watch, onMounted } from 'vue'
44 import type { Field } from '@/types/field'
45 interface FieldProps {
46 modelValue: string | number | null | undefined
47 field: Field
48 disabled?: boolean
49 error?: string
50 }
51
52 const props = withDefaults(defineProps<FieldProps>(), {
53 modelValue: '',
54 disabled: false,
55 error: '',
56 })
57
58 const emit = defineEmits(['update:modelValue'])
59
60 const fieldID = `field_${props.field.fieldIndex}`
61 const localModelValue = ref(props.modelValue)
62
63 watch(
64 () => props.modelValue,
65 (newVal) => {
66 localModelValue.value = newVal
67 },
68 )
69 watch(localModelValue, (newVal) => {
70 emit('update:modelValue', newVal)
71 })
72 const disabled = computed(() => props.disabled || props.field.readOnly)
73 const error = computed(() => props.error || '')
74 const field = computed(() => props.field)
75
76 // Shuffle options only once on mount
77 const shuffledOptions = ref([])
78 function shuffle<T>(array: T[]): T[] {
79 const arr = array.slice()
80 for (let i = arr.length - 1; i > 0; i--) {
81 const j = Math.floor(Math.random() * (i + 1))
82 ;[arr[i], arr[j]] = [arr[j], arr[i]]
83 }
84 return arr
85 }
86 onMounted(() => {
87 let opts = field.value.fieldOptions || []
88 if (field.value.shuffleOptions) {
89 opts = shuffle(opts)
90 }
91 shuffledOptions.value = opts.map((opt) => ({
92 label: opt.label,
93 value: opt.value,
94 id: opt.id,
95 }))
96 })
97 const radioOptions = computed(() =>
98 shuffledOptions.value.length
99 ? shuffledOptions.value
100 : (field.value.fieldOptions || []).map((opt) => ({
101 label: opt.label,
102 value: opt.value,
103 id: opt.id,
104 })),
105 )
106 </script>
107